1// This code demonstrates: 2// 3// - A class derived from c4_Strategy to implement encrypted storage. 4// - Disabling the Flush calls issued during Commit() for speed. 5// - Using c4_Strategy objects as the basis of all file I/O in Metakit. 6 7#include "mk4.h" 8#include "mk4io.h" 9 10#include <string.h> 11 12///////////////////////////////////////////////////////////////////////////// 13// This derived strategy encrypts its data on disk and omits flushes 14 15class CEncryptStrategy : public c4_FileStrategy 16{ 17public: 18 CEncryptStrategy (const char* fileName_, bool rw_); 19 virtual ~CEncryptStrategy (); 20 21 // Reading and writing of course messes around with all the data 22 virtual int DataRead(long, void*, int); 23 virtual void DataWrite(long, const void*, int); 24 25 // For this example, we also disable all explicit file flushes 26 virtual void DataCommit(long) { } 27 28 // Cannot use memory mapped file access when decoding on the fly 29 virtual void ResetFileMapping() { } 30 31private: 32 // This example uses a trivial encoding, incorporating offsets. 33 static char Encode(long pos, char c_) 34 { return (char) (c_ ^ pos ^ 211); } 35 static char Decode(long pos, char c_) 36 { return (char) (c_ ^ pos ^ 211); } 37}; 38 39CEncryptStrategy::CEncryptStrategy (const char* fileName_, bool rw_) 40{ 41 c4_FileStrategy::DataOpen(fileName_, rw_); 42} 43 44CEncryptStrategy::~CEncryptStrategy () 45{ 46} 47 48int CEncryptStrategy::DataRead(long lOff, void* lpBuf, int nCount) 49{ 50 int result = 0; 51 52 if (nCount > 0) 53 { 54 char* ptr = (char*) lpBuf; 55 56 result = c4_FileStrategy::DataRead(lOff, ptr, nCount); 57 58 for (int i = 0; i < result; ++i) 59 ptr[i] = Decode(lOff++, ptr[i]); 60 } 61 62 return result; 63} 64 65void CEncryptStrategy::DataWrite(long lOff, const void* lpBuf, int nCount) 66{ 67 if (nCount > 0) 68 { 69 c4_Bytes buf; 70 char* ptr = (char*) buf.SetBuffer(nCount); 71 72 memcpy(ptr, lpBuf, nCount); 73 74 for (int i = 0; i < nCount; ++i) 75 ptr[i] = Encode(lOff++, ptr[i]); 76 77 c4_FileStrategy::DataWrite(lOff - nCount, ptr, nCount); 78 } 79} 80 81///////////////////////////////////////////////////////////////////////////// 82 83int main() 84{ 85 // This property could just as well have been declared globally. 86 c4_StringProp pLine ("line"); 87 88 { 89 // This is where the magic takes place. 90 CEncryptStrategy efile ("secret.dat", true); 91 92 c4_Storage storage (efile); 93 94 static const char* message[] = { 95 "This is a small message which will be encrypted on file.", 96 "As a result, none of the other Metakit utilities can read it.", 97 "Furthermore, a hex dump of this file will produce gibberish.", 98 "The encryption used here is ridiculously simple, however.", 99 "Beware of naive encryption schemes, cracking them is a sport.", 100 0 101 }; 102 103 // Store the text lines as separate entries in the view. 104 c4_View vText; 105 106 for (const char** p = message; *p; ++p) 107 vText.Add(pLine [*p]); 108 109 // changed 2000-03-15: Store is gone 110 //storage.Store("text", vText); 111 c4_View v2 = storage.GetAs("text[line:S]"); 112 v2.InsertAt(0, vText); 113 114 storage.Commit(); 115 } 116 117 // The end of the preceding block will flush out all data to file. 118 { 119 // Repeat the process when accessing the encrypted file again. 120 CEncryptStrategy efile ("secret.dat", false); 121 122 c4_Storage storage (efile); 123 c4_View vText = storage.View("text"); 124 125 for (int i = 0; i < vText.GetSize(); ++i) 126 { 127 const char* s = pLine (vText[i]); 128 puts(s); 129 } 130 } 131 132 // At this point, an encrypted data file is left behind on the disk. 133 134 return 0; 135} 136 137///////////////////////////////////////////////////////////////////////////// 138