raSystem  1.0 bata
raFile.cpp
Go to the documentation of this file.
1 #include "..\include\raMain.h"
2 
3 namespace raSystem
4 {
5  struct raZipHeader
6  {
7  DWORD dwSignature;
13  DWORD dwCRC32;
18  };
19  //#pragma pack(pop)
20 
21  raFile::raFile(void)
22  {
23  }
24 
25 
26  raFile::~raFile(void)
27  {
28  }
29 
30 
31 
32 
33  DWORD raCRC32Table[256]; // CRC32-Tabelle für die Entschlüsselung
34  BOOL raCRC32TableFilled = FALSE; // Ist die Tabelle gefüllt?
35 
36  DWORD raCRC32(DWORD a, BYTE b)
37  {
38  // Liefert den CRC32-Wert zweier Zahlen zurück
39  return raCRC32Table[(a ^ b) & 0xFF] ^ (a >> 8);
40  }
41  bool raFile::FillCRC32Table()
42  {
43  DWORD c;
44 
45  if(raCRC32TableFilled)
46  return true;
47 
48  // Tabelle mit speziellem Verfahren ausfüllen
49  for(DWORD a = 0; a < 256; a++)
50  {
51  c = a;
52  for(int b = 0; b < 8; b++)
53  {
54  c = c & 1 ? 0xEDB88320 ^ (c >> 1) : c >> 1;
55  }
56 
57  // Eintrag speichern
58  raCRC32Table[a] = c;
59  }
60 
61  // Tabelle gefüllt
62  raCRC32TableFilled = TRUE;
63  RINFO("CRC32-Tabelle wurde generiert!");
64 
65  return true;
66  }
67  bool raFile::UpdateZipKeys(DWORD* pdwKey, BYTE c)
68  {
69  if(!pdwKey)
70  return false;
71  pdwKey[0] = raCRC32(pdwKey[0], c);
72  pdwKey[1] += pdwKey[0] & 0x000000FF;
73  pdwKey[1] = pdwKey[1] * 134775813 + 1;
74  pdwKey[2] = raCRC32(pdwKey[2], (BYTE)(pdwKey[1] >> 24));
75 
76  return true;
77  }
78 
79  BYTE DecryptZipByte(DWORD* pdwKey)
80  {
81  WORD wTemp;
82  wTemp = (WORD)(pdwKey[2] | 2);
83  return (((wTemp * (wTemp ^ 1)) >> 8) & 0xFF);
84  }
85  bool raFile::DecryptZipObject(DWORD dwObjectCRC32, BYTE* pEncryptionHeader, BYTE* pData,
86  raString pcPassword)
87  {
88  DWORD adwKey[3]; // Die drei Schlüssel
89  BYTE Temp; // Temporäre Variable
90  int iSize; // Größe des Objekts
91 
92 
93  if(!pData) { RERROR_NULLPOINTER("pData"); return false; }
94 
95 
96  // Wenn die CRC32-Tabelle noch nicht ausgefüllt wurde, dann wird
97  // das jetzt getan.
98  if(!raCRC32TableFilled)
99  FillCRC32Table();
100 
101  // Die drei Schlüssel initialisieren
102  adwKey[0] = 305419896;
103  adwKey[1] = 591751049;
104  adwKey[2] = 878082192;
105 
106  // Schlüssel auf Passwort einstellen
107  for(int a = 0; a < (int)(strlen(pcPassword.c_str())); a++)
108  UpdateZipKeys(adwKey, (BYTE)(pcPassword[a]));
109 
110  // Verschlüsselungsheader entschlüsseln
111  for(int a = 0; a < 12; a++)
112  {
113  Temp = *((BYTE*)(pEncryptionHeader) + a) ^ DecryptZipByte(adwKey);
114  pEncryptionHeader[a] = Temp;
115  UpdateZipKeys(adwKey, Temp);
116  }
117 
118  // Testen, ob das Passwort in Ordnung war
119  if((BYTE)((dwObjectCRC32 & 0xFF000000) >> 24) != pEncryptionHeader[11]) return false;
120 
121  // Nun werden die Daten entschlüsselt.
122  iSize = raSystem::raMemManager::Instance().MemGetSize(pData);
123  for(int a = 0; a < iSize; a++)
124  {
125  Temp = pData[a] ^ DecryptZipByte(adwKey);
126  pData[a] = Temp;
127  UpdateZipKeys(adwKey, Temp);
128  }
129 
130  return true;
131  }
132 
133  // ******************************************************************
134  // Passwort entschlüsseln
135  bool raFile::DecryptPassword( raString pcPassword)
136  {
137  // Schlüsselwerte, die zum Entschlüsseln des Passworts benötigt werden
138  int aiKey[50] = {0x02, 0x03, 0x05, 0x07, 0x11, 0x13, 0x17, 0x19, 0x23, 0x29,
139  0xA2, 0xB3, 0xC5, 0xD7, 0xE1, 0xF3, 0xA7, 0xB9, 0xC3, 0xD9,
140  0x93, 0xA4, 0xB6, 0xC8, 0xD2, 0xE4, 0x98, 0xA8, 0xB4, 0xC8,
141  0x46, 0x58, 0x63, 0x67, 0x74, 0x78, 0x57, 0x57, 0x68, 0x67,
142  0xA9, 0xBC, 0xC9, 0xDF, 0xF6, 0x0C, 0xBF, 0xCF, 0xFC, 0xFF};
143 
144  int iHexToDec[256]; // Umrechungstabelle
145  char acPassword[256]; // Neues Passwort
146 
147 
148  // Hexadezimaltabelle initialisieren
149  ZeroMemory(iHexToDec, 256 * sizeof(int));
150  iHexToDec['0'] = 0;
151  iHexToDec['1'] = 1;
152  iHexToDec['2'] = 2;
153  iHexToDec['3'] = 3;
154  iHexToDec['4'] = 4;
155  iHexToDec['5'] = 5;
156  iHexToDec['6'] = 6;
157  iHexToDec['7'] = 7;
158  iHexToDec['8'] = 8;
159  iHexToDec['9'] = 9;
160  iHexToDec['A'] = iHexToDec['a'] = 10;
161  iHexToDec['B'] = iHexToDec['b'] = 11;
162  iHexToDec['C'] = iHexToDec['c'] = 12;
163  iHexToDec['D'] = iHexToDec['d'] = 13;
164  iHexToDec['E'] = iHexToDec['e'] = 14;
165  iHexToDec['F'] = iHexToDec['f'] = 15;
166 
167  // Das Passwort liegt im Hexadezimalformat vor. Dieses wandeln
168  // wir jetzt in Bytefolgen um.
169  ZeroMemory(acPassword, 256 * sizeof(char));
170  for(int a = 0; a < (int)(strlen(pcPassword.c_str())); a += 2)
171  {
172  acPassword[a / 2] = iHexToDec[pcPassword[a]] * 16 +
173  iHexToDec[pcPassword[a + 1]];
174  }
175 
176 
177  // Das Passwort wird entschlüsselt.
178  // Zuerst wird seine Länge verwendet, um den Zufallszahlen-
179  // generator zu initialisieren. Das Initialisieren passiert
180  // mehrfach, um eine höhere Sicherheit zu gewährleisten.
181 #ifndef WIN64
182  srand(strlen(acPassword) * 17);
183 #else
184  size_t len = strlen(acPassword);
185  srand(UINT(len * 17));
186 #endif
187  for(int a = 0; a < (int)(strlen(acPassword)); a++)
188  {
189  // Zufallszahlengenerator initialisieren
190 #ifndef WIN64
191  srand(rand() + strlen(acPassword) * a);
192 #else
193  len = strlen(acPassword);
194  srand(UINT(rand() + len * a));
195 #endif
196  srand((rand() % (aiKey[a % 50])) + (rand() % (aiKey[(a * 23) % 50])));
197  srand((rand() % (aiKey[(a + 2305) % 50])) + (rand() % (aiKey[(17 + a * 133) % 50])) * 177);
198 
199  // Entschlüsselung des Passworts vornehmen
200  pcPassword[a] = acPassword[a] - (rand() % 256);
201 
202  // Zufallszahlengenerator erneut initialisieren
203  srand(((BYTE)(acPassword[a]) + 1) * (a + 23) + (rand() % 1381));
204  }
205 
206  return true;
207  }
208 
209  // ******************************************************************
210  // Eine Datei einlesen (alle Typen)
211  bool raFile::ReadFile( raString pcFilename, void** ppOut)
212  {
213  char acFilename[256]; // Kopie des Dateinamens (zum Basteln)
214  raString *pcAt; // Position des "@"-Zeichens im Dateinamen
215  raString *pcLeft; // Linker Teil des Dateinamen
216  raString *pcRight; // Linker Teil des Dateinamen
217  raString *pcPassword; // Passwort
218 
219 
220  // Dateiname kopieren
221  strcpy(acFilename, pcFilename.c_str());
222  pcFilename = acFilename;
223 
224  // Nach einem "@"-Zeichen im Dateinamen suchen.
225  // Falls eines gefunden wird, wird der Dateiname an dieser Stelle
226  // geteilt - der vordere Teil ist der Objektname und der hintere
227  // der Dateiname der enthaltenden Datei.
228  pcAt = new raString(strrchr(pcFilename.c_str(), '@'));
229  if(!pcFilename.find('@'))
230  {
231  // Kein "@"-Zeichen gefunden! Die Datei wird ganz normal
232  // eingelesen. Dazu rufen wir ReadRawFile auf.
233  return ReadRawFile(pcFilename, ppOut);
234  }
235 
236  // Es ist also ein "@"-Zeichen im Dateinamen.
237  // Wir kennen seine Position, also können wir den Dateinamen in
238  // zwei Strings aufteilen. Das "@"-Zeichen ersetzen wir einfach
239  // durch eine binäre null, damit dort der erste String endet.
240  *pcAt = raString(0);
241  pcLeft = new raString(pcFilename);
242  pcRight = pcAt + 1;
243 
244  // Falls versucht wird, eine verschlüsselte Zip-Datei zu lesen,
245  // muss zusätzlich ein Passwort angegeben werden. Es beginnt nach
246  // dem ">"-Zeichen, was wir jetzt suchen.
247  pcPassword = new raString(strrchr(pcRight->c_str(), '>'));
248  if(pcPassword->c_str())
249  {
250  // Das ">"-Zeichen wurde gefunden.
251  // Es wird durch eine binäre Null ersetzt, damit der String
252  // des Dateinamen der Zip-Datei dort endet.
253  *pcPassword = raString(0);
254  pcPassword++;
255 
256  // Wenn das Passwort verschlüsselt ist, wird es jetzt entschlüsselt.
257  if(*pcPassword->c_str() == '?')
258  DecryptPassword(*(++pcPassword));
259  }
260 
261  // Nun können wir die Zip-Dateifunktion aufrufen.
262  return ReadZipFileObject(*pcRight, *pcLeft, *pcPassword, ppOut);
263  }
264 
265  // ******************************************************************
266  // Zip-Objekt lesen
267  bool raFile::ReadZipFileObject( raString pcZipFilename, raString pcObjectName,
268  raString pcPassword, void** ppOut)
269  {
270  FILE* pZipFile; // Handle der geöffneten Zip-Datei
271  raZipHeader ZipHeader; // Header der Zip-Datei
272  char acObjectName[256]; // Name des aktuellen Objekts
273  BOOL bFinished; // Fertig mit dem Lesen?
274  BOOL bEncrypted; // Sind die Daten verschlüsselt?
275  BYTE aEncryptionHeader[12]; // 12 Bytes großer Verschlüsselungsheader
276  void* pData; // Daten des Objekts
277  int iSize; // Größe des Objekts
278 
279 
280 
281 
282  // Datei binär zum Lesen öffnen
283  pZipFile = fopen(pcZipFilename.c_str(), "rb");
284  if(!pZipFile)
285  {
286  RERROR_FILE(pcZipFilename);
287  return false;
288  }
289 
290  // Die Zip-Datei ist geöffnet.
291  // Wir lesen jetzt so lange Objekte ein, bis wir das passende
292  // gefunden haben.
293  bFinished = FALSE;
294  bEncrypted = FALSE;
295  while(!bFinished)
296  {
297  // Den Header einlesen
298  if(fread(&ZipHeader, sizeof(raZipHeader), 1, pZipFile) != 1)
299  {
300  fclose(pZipFile);
301  RERROR("Fehler beim Lesen des Headers!");
302  return false;
303  }
304 
305  // Prüfen, ob die Signatur stimmt. Falls nicht, sind wohl
306  // alle Dateien gelesen worden.
307  if(ZipHeader.dwSignature != 0x04034B50)
308  {
309  fclose(pZipFile);
310  RERROR("Das Objekt wurde nicht gefunden!");
311  return false;
312  }
313 
314  // Falls Bit Nr. 1 des wGeneralPurpose-Elements gesetzt ist,
315  // sind die Daten dieses Objekts verschlüsselt.
316  if(ZipHeader.wGeneralPurpose & 0x0001) bEncrypted = TRUE;
317 
318  // Dateiname (Objektname) einlesen
319  ZeroMemory(acObjectName, 256 * sizeof(char));
320  if(fread(acObjectName, ZipHeader.wFilenameLength, 1, pZipFile) != 1)
321  {
322  fclose(pZipFile);
323  RERROR("Fehler beim Lesen des Dateinamens!");
324  return false;
325  }
326 
327  // Vergleichen
328  if(!_stricmp(pcObjectName.c_str(), acObjectName))
329  {
330  // Das richtige Objekt wurde gefunden!
331  bFinished = TRUE;
332  }
333 
334  // Die Extradaten überspringen
335  fseek(pZipFile, ZipHeader.wExtraLength, SEEK_CUR);
336 
337  if(!bFinished)
338  {
339  // Die Daten des Objekts überspringen, falls es sich nicht
340  // um das gesuchte Objekt handelt.
341  fseek(pZipFile, ZipHeader.dwCompressedSize, SEEK_CUR);
342 
343  // Falls Bit Nr. 4 des wGeneralPurpose-Elements des Headers
344  // gesetzt ist, folgt ein weiterer Datenbereich, den wir aber
345  // nicht brauchen und einfach überspringen können.
346  if(ZipHeader.wGeneralPurpose & 0x0008)
347  fseek(pZipFile, 12, SEEK_CUR);
348  }
349  }
350 
351 
352  // Das Objekt wurde gefunden!
353  // Es muss unkomprimiert sein, um gelesen zu werden.
354  if(ZipHeader.wCompressionMethod != 0)
355  {
356  fclose(pZipFile);
357  RERROR("Komprimiertes Objekt gefunden! Dekomprimierung wird nicht unterstützt!");
358  return false;
359  }
360 
361  // Falls das Objekt verschlüsselt ist, wird der 12 Bytes große
362  // Verschlüsselungsheader, der sich vor den eigentlichen Daten
363  // befindet, eingelesen werden.
364  if(bEncrypted)
365  {
366  if(fread(aEncryptionHeader, 12, 1, pZipFile) != 1)
367  {
368  fclose(pZipFile);
369  RERROR("Fehler beim Lesen des Verschlüsselungs-Headers!");
370  return false;
371  }
372  }
373 
374  // Speicher wird für die Daten reserviert.
375  pData = raSystem::raMemManager::Instance().MemAlloc(ZipHeader.dwCompressedSize - (bEncrypted ? 12 : 0));
376  if(!pData)
377  {
378  RERROR_OUTOFMEM();
379  return false;
380  }
381  // Daten einlesen
382  iSize = raSystem::raMemManager::Instance().MemGetSize(pData);
383  if(fread(pData, iSize, 1, pZipFile) != 1)
384  {
385  raSystem::raMemManager::Instance().MemFree(pData);
386  fclose(pZipFile);
387  RERROR("Fehler beim Lesen der Objektdaten!");
388  return false;
389  }
390 
391  // Entschlüsseln, falls nötig
392  if(bEncrypted)
393  {
394  if(DecryptZipObject(ZipHeader.dwCRC32, aEncryptionHeader,
395  (BYTE*)(pData), pcPassword))
396  {
397  raSystem::raMemManager::Instance().MemFree(pData);
398  fclose(pZipFile);
399  RERROR("Entschlüsselung fehlgeschlagen!");
400  return false;
401  }
402  }
403 
404  // Datei schließen und Pointer zurückliefern
405  fclose(pZipFile);
406 
407  // Zeiger liefern
408  *ppOut = pData;
409 
410  return true;
411  }
412 
413  // ******************************************************************
414  // "Rohe" Datei lesen
415  bool raFile::ReadRawFile( raString pcFilename, void** ppOut)
416  {
417  struct stat FileStats; // Statistiken der Datei
418  void* pData; // Daten aus der Datei
419  FILE* pFile; // Dateihandle
420 
421  // Statistiken der Datei abfragen (wir brauchen nur die Größe)
422  ZeroMemory(&FileStats, sizeof(struct stat));
423  stat(pcFilename.c_str(), &FileStats);
424  if(FileStats.st_size <= 0) { RERROR_FILE(pcFilename); return false; }
425 
426  // Speicherbereich reservieren, der groß genug ist
427  pData = raSystem::raMemManager::Instance().MemAlloc(FileStats.st_size);
428  if(!pData)
429  {
430  RERROR_OUTOFMEM();
431  return false;
432  }
433 
434  // Datei binär zum Lesen öffnen
435  pFile = fopen(pcFilename.c_str(), "rb");
436  if(!pFile)
437  {
438  raSystem::raMemManager::Instance().MemFree(pData);
439  RERROR_FILE(pcFilename);
440  return false;
441  }
442 
443  // Daten lesen
444  if(fread(pData, FileStats.st_size, 1, pFile) != 1)
445  {
446  raSystem::raMemManager::Instance().MemFree(pData);
447  fclose(pFile);
448  RERROR_FILE(pcFilename);
449  return false;
450  }
451 
452  // Datei schließen und Pointer zurückliefern
453  fclose(pFile);
454 
455  // Zeiger liefern
456  *ppOut = pData;
457 
458  return true;
459  }
460 
461  // ******************************************************************
462  // Daten in eine Datei schreiben
463  bool raFile::WriteFile( raString pcFilename, void* pData, int iNumBytes)
464  {
465  FILE* pFile; // Dateihandle
466 
467  // Parameter prüfen
468  if(!pData) { RERROR_NULLPOINTER("pData"); return false; }
469  if(iNumBytes <= 0) { RERROR_INVALIDVALUE("iNumBytes");return false; }
470 
471 
472  // Datei zum Schreiben im Binärmodus öffnen
473  pFile = fopen(pcFilename.c_str(), "wb");
474  if(!pFile)
475  {
476  RERROR_FILE(pcFilename);
477  return false;
478  }
479 
480  // Daten schreiben
481  if(fwrite(pData, iNumBytes, 1, pFile) != 1)
482  {
483  fclose(pFile);
484  RERROR_FILE(pcFilename);
485  return false;
486  }
487 
488  // Datei schließen und fertig
489  fclose(pFile);
490 
491  return true;
492  }
493 };
DWORD raCRC32Table[256]
Definition: raFile.cpp:33
DWORD dwUncompressedSize
Definition: raFile.cpp:15
BYTE DecryptZipByte(DWORD *pdwKey)
Definition: raFile.cpp:79
void RAPI RERROR_FILE(raString f)
Definition: raMain.cpp:149
void RAPI RERROR_INVALIDVALUE(raString x)
Definition: raMain.cpp:139
DWORD raCRC32(DWORD a, BYTE b)
Definition: raFile.cpp:36
void RAPI RERROR_NULLPOINTER(raString x)
Definition: raMain.cpp:134
std::string raString
Definition: raMain.h:107
ID3D11Buffer D3D11_BUFFER_DESC void * pData
Definition: raSDKmesh.h:238
void RAPI RINFO(raString x)
Definition: raMain.cpp:119
void RAPI RERROR_OUTOFMEM()
Definition: raMain.cpp:144
void RAPI RERROR(raString x)
Definition: raMain.cpp:129
BOOL raCRC32TableFilled
Definition: raFile.cpp:34