Click here to Skip to main content
16,016,489 members
Articles / Programming Languages / C++

Literal String Encryption as Part of the Build Process

Rate me:
Please Sign up or sign in to vote.
4.87/5 (23 votes)
17 Mar 2005CPOL6 min read 231.3K   2.1K   79   53
CXR allows you to create encrypted strings at compile time.
This article will show you how to use strings for messages, passwords or other text inside your app that does not require you to use a literal string in CXR.

Introduction

Have you ever wished there was a way to use strings for messages, passwords or other text inside your app that didn't require you to use a literal string, because you were worried about someone finding the strings in your EXE ? Wish no more, CXR is here.

What Does It Do?

CXR is a combination of a text parser, a stream cipher and C source code generator. You define your literal text strings in a ".CXR" file as part of your normal coding process, using standard C/C++ constructs. Then, when you build your project, the CXR program will encrypt those strings and generate a new .CPP file that is compiled into your project, automatically. The process is somewhat like what happens with .IDL files when you are working on an ATL project.

What?

Here's an example:

You create a .CXR file that contains your string definitions and a unique password:

C++
////////////////////
// my .CRX file
//
// here is my password definition:
// CXRP = "SexyBeast"		
//
// here are some strings:				

// my first string   
const char* pString1 = _CXR("AbcdEfg1234  blah\tblah"); 

// string #2
const char* pString2
       = _CXR("This is a long one, not that it should matter...");

As you can see, the only difference between this and standard C/C++ is the _CXR specifier. The comment line with the password is required, and any text you want encrypted must be inside a _CXR(...) specifier. Anything else in the file will be copied over to the output .CPP unchanged. So, that's how you set up the .CXR file. When you build your project, the CXR parser will read this file and generate a .CPP that looks like this:

C++
///////////////////////////
#ifdef _USING_CXR
// my first string
const char* pString1 = "ab63103ff470cb642b7c319cb56e2dbd591b63a93cf88a";
#else
const char* pString1 = _CXR("AbcdEfg1234  blah\tblah");  // my first string
#endif

///////////////////////////
#ifdef _USING_CXR

// string #2
const char* pString2 = 
    "baff195a3b712e15ee7af636065910969bb24997c49c6d0cc6a40d3ec1...";
#else
// string #2
const char* pString2 = 
    _CXR("This is a long one, not that it should matter..."); 
#endif
...more stuff below...

Presto. The CXR parser has encrypted your strings.

Ok, How Do I Get My Strings Back?

The "...more stuff below..." is actually the decryptor code. That decryptor code is compiled into your project, with the CXR password you gave. So, all you have to do to is this:

C++
CString csString1 = _CRX(pString1);
// pString1 = "ab63103ff470cb642b7c319cb56e2dbd591b63a93cf88a"
// and now csString1 = "AbcdEfg1234  blah\tblah";

Note the #ifdef _USING_CXR tags. Because of these, you can disable the CXR strings by simply changing a single #define - to make testing easier. If _USING_CXR is not defined, all your strings revert to their unencrypted form and the "_CXR" turns into a macro that does nothing. If _USING_CXR is defined, your strings take on their encrypted forms and the _CXR macro becomes a call to the decrypting code. It's (almost) totally seamless.

It Can't Be That Easy

Well, it's almost that easy. There are some steps you need to follow to add your .CRX file to your project and to enable the CXR parser. But, these are all one-time things. Once you set them up the first time, you never have to do it again.

Setting Up

  1. Build the CXR.EXE and put it somewhere in your path (in your WinNT or Windows folder, perhaps).
  2. Create your .CRX file. Create a file that has your password definition and your literal text strings. Follow these rules:
    • A .CXR file must contain a password line of the form:
      C++
      // CXRP = "MyPasswordString"
      Where the password string is any string you want. The "// CXRP =" part is required.
    • All text strings that are to be encrypted must be enclosed in a _CXR(...) tag.
    • _CXR(...) tags cannot span multiple lines.
    • CXR currently does not support Unicode. All your strings will be treated by the encoder as if they were ANSI strings. Using this in a Unicode build will probably cause you huge headaches. Unicode support is planned in the future, but it isn't supported right now.
  3. Create a .H file for your strings. Really, this is just a basic C/C++ issue. CXR will generate a .CPP file with your encoded strings. But, as with any extern strings, if you want to use them in your code, you have to define them somewhere. In the example above, I would create a file called "strings.h" and add the following:
    C++
    extern const char* pString1;
    extern const char* pString2;
  4. Add the .CXR file to your project. You have to do this manually (right click on your project in the File View, select the .CXR file, etc.).
  5. Add a new .CPP file to your project. The CXR parser will generate a .CPP file for you. But, you have to tell the compiler to compile it. So, add another file to your project. If your .CXR file was named "Strings.CXR", add "Strings.CPP" to your project - just type in the name when the file dialog pops up. Since this file doesn't exist yet, Visual Studio will ask if you want to add a reference to it anyway. Say Yes. The first time you build, the .CPP will be created.
  6. Set the custom build options. Find your .CXR file in the Project / Settings menu. Check "Always use custom build step". On the Custom Build tab, in the "Commands" section, enter the following:
    cxr.exe -i $(InputPath) -o $(ProjDir)\$(InputName).cpp
    This will cause Visual Studio to call CXR.EXE with the name of your .CXR file as input and the same name, but with a .CPP extension as output.

    In the "Outputs" section, enter:

    $(ProjDir)\$(InputName).cpp
    This tells the compiler that this file needs to be recompiled when the .CXR file changes.
  7. Add cxr_inc.h to your project and add #include "cxr_inc.h" in every file in which you want to use the encrypted strings. There is a copy of this file in the sample "Test" project. But, it looks just like this:
    C++
    #ifndef CRXHeaderH
    #define CRXHeaderH
    
    #define _USING_CXR
    
    #ifndef _USING_CXR
    #define _CXR(x) x
    
    #else
    
    #define _CXR(x) __CXRDecrypt(x)
    extern CString __CXRDecrypt(const char *pIn);
    
    #endif
    
    #endif
    This file defines the macros you need to use to get your strings. This is also a good place to turn off the _USING_CXR macro, if you want to use your strings un-encrypted for any reason.
  8. That's it! I know it looks like a lot. But again, the previous steps only have to be done once. After the setup is complete, the only interaction you'll have with CXR is when you edit and access your strings.

In Detail

CXR is fairly simple. The parser scans the .CXR input file, looking for two things: 1. the password line and 2. quoted strings inside _CXR(...) tags. Anything else it just copies to the output as-is. When it finds a _CXR tag, it encrypts the string with your password, converts the encrypted data to printable characters and outputs the encrypted version, along with the original version, in an #ifdef...#endif chunk. The parser is somewhat dumb; it doesn't understand much C/C++; it only knows to looks for the password and _CXR("..."), this is what prevents the use of multi-line text and Unicode. It does, however understand the syntax of C/C++ literal strings (including all escapes documented in K&R v2).

The encryption code is based on the quick and small Sapphire II stream cipher, from Crypto++. XOR would work equally as well, since we're only concerned about obfuscating the strings, not in keeping them secure against decryption attack.

You Must Be Stupid. This Won't Stop Crackers

No, I'm not stupid. I know that this by itself won't stop crackers. This is only a part of a complete defense. Of course, if they find and watch the CXR decryption code, they can see the decrypted strings coming out; but they would have to know to look for it and find it, first. What CXR really does is it stops them from finding your "Registration complete!" and "Your trial period has expired!" messages with a simple string scan of the .EXE. Protection against crackers (as cracking itself) is a black art, not a science. As I see it, every twist and turn you can throw at the crackers stands a chance of being the one that causes them to give up and move on to the next target. Every barrier you can put in their way is a good one.

Updates

  • 9th August, 2002
    • Changed character encoding from hex digits (1,2,3..f) to offset-based. This obscures the strings even better.
    • Fixed the demo package
  • 17th March, 2005
    • Updated source code

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United States United States
Chris Losinger was the president of Smaller Animals Software, Inc. (which no longer exists).

Comments and Discussions

 
PraiseGreat article Pin
Member 1452198417-Aug-22 7:43
Member 1452198417-Aug-22 7:43 
QuestionRandom Password Pin
ChRoNoN4-Feb-15 1:35
ChRoNoN4-Feb-15 1:35 
AnswerRe: Random Password Pin
Chris Losinger4-Feb-15 3:24
professionalChris Losinger4-Feb-15 3:24 
GeneralMy vote of 5 Pin
Michael Haephrati4-Dec-12 2:18
professionalMichael Haephrati4-Dec-12 2:18 
Newscxr branch on google code Pin
paleozogt13-Jan-10 5:32
paleozogt13-Jan-10 5:32 
Generaldirect encryption Pin
patrick.steal20-Jul-07 6:45
patrick.steal20-Jul-07 6:45 
GeneralRe: direct encryption [modified] Pin
Chris Losinger20-Jul-07 6:57
professionalChris Losinger20-Jul-07 6:57 
Questionweird problem Pin
patrick.steal3-Jul-07 7:17
patrick.steal3-Jul-07 7:17 
AnswerRe: weird problem Pin
Chris Losinger3-Jul-07 7:36
professionalChris Losinger3-Jul-07 7:36 
News! Two Problems [modified] Pin
Synetech23-May-06 5:16
Synetech23-May-06 5:16 
GeneralThings I had to change to compile CXR Pin
Hokei2-Mar-06 10:41
Hokei2-Mar-06 10:41 
GeneralRe: Things I had to change to compile CXR Pin
Hokei14-Mar-06 20:42
Hokei14-Mar-06 20:42 
I rewrote all the source to use STL classes instead of MFC. I didn't want to use MFC, and it's not portable anyway. If anyone is interested, here is the source. I apologize in advance if the Code Project comment engine screws up any of the code as I try to post it.

CXR_standard.cpp:
<br />
// CXR_Standard.cpp<br />
//<br />
// BASED ON code from Smaller Animals Software. Their copyright notice<br />
// follows. Usage: CXR -i [filename.cpp] -o [filename.cpp]<br />
//<br />
//********************************************************************<br />
//<br />
//   Copyright (C) 2002 Smaller Animals Software, Inc.<br />
//<br />
//   This software is provided 'as-is', without any express or implied<br />
//   warranty.  In no event will the authors be held liable for any damages<br />
//   arising from the use of this software.<br />
//<br />
//   Permission is granted to anyone to use this software for any purpose,<br />
//   including commercial applications, and to alter it and redistribute it<br />
//   freely, subject to the following restrictions:<br />
//<br />
//   1. The origin of this software must not be misrepresented; you must not<br />
//     claim that you wrote the original software. If you use this software<br />
//     in a product, an acknowledgment in the product documentation would be<br />
//     appreciated but is not required.<br />
//<br />
//   2. Altered source versions must be plainly marked as such, and must not be<br />
//     misrepresented as being the original software.<br />
//<br />
//   3. This notice may not be removed or altered from any source distribution.<br />
//<br />
//   http://www.smalleranimals.com<br />
//   smallest@smalleranimals.com<br />
//<br />
//*********************************************************************<br />
<br />
#include "stdafx.h"<br />
#include <string><br />
#include <iostream><br />
#include <fstream><br />
#include <time.h><br />
#include "Tokenizer.h"<br />
#include "Stream.h"<br />
<br />
using namespace std;<br />
<br />
static bool    ProcessFile(ifstream &in, const string &strInFilename, ofstream &out, const string &strOutFilename);<br />
static bool    AddDecode(const string &strPassword, ofstream &out);<br />
static string  Encrypt(const string &strIn, const char* pPass);<br />
static string  Decrypt(const char* pIn, const char* pPass);<br />
static bool    ExpandOctal(const string &strIn, string &strOut, int &iConsumed);<br />
static string  TranslateString(const string &strIn);<br />
static bool    ExpandHex(const string &strIn, string &strOut, int &iConsumed);<br />
static string  EscapeString(const char* pIn);<br />
<br />
// The basechar is added/subtracted with every character as part of the <br />
// encrypt/decrypt process, but for what -- obfuscation?<br />
// These can be adjusted in the range 1 to 239:<br />
const int basechar1 = 128;<br />
const int basechar2 = 128;<br />
<br />
int _tmain(int argc, _TCHAR* argv[])<br />
{<br />
  int nRetCode = 0;<br />
<br />
  srand((unsigned int)time(NULL));<br />
<br />
  cerr << _T("Starting CXR, the literal string encryptor. Copyright 2002, Smaller Animals Software Inc.") << endl;<br />
<br />
  if ((basechar1 == 0) || (basechar2 == 0) || (basechar1 > 239) || (basechar2 > 239))<br />
  {<br />
    cerr << _T("CXR basechar values out of acceptable range. Aborting") << endl;<br />
    nRetCode = 1;<br />
    return nRetCode;<br />
  }<br />
<br />
  if (argc >= 2)<br />
  {<br />
    //TODO: Smarter command line argument parsing:<br />
    string strInFile = argv[2];<br />
    string strOutFile = argv[4];<br />
<br />
    if (!strInFile.empty() && !strOutFile.empty())<br />
    {<br />
      // open the input file (always an ANSI file)<br />
      ifstream fileIn;<br />
<br />
      // open the output file (always an ANSI file)<br />
      ofstream fileOut;<br />
         <br />
      fileIn.open(strInFile.c_str(), ios::in);<br />
      if(fileIn.is_open())<br />
      {<br />
        fileOut.open(strOutFile.c_str(), ios::trunc | ios::out);<br />
        if(fileOut.is_open())<br />
        {<br />
          if (!ProcessFile(fileIn, strInFile, fileOut, strOutFile))<br />
          {<br />
            cerr << _T("CXR failed") << endl;<br />
            nRetCode = 1;<br />
          }<br />
        }<br />
        else<br />
        {<br />
          cerr << _T("Unable to open output file: ") << strOutFile << endl;<br />
          nRetCode = 1;<br />
        }<br />
      }<br />
      else<br />
      {<br />
        cerr << _T("Unable to open input file: ") << strInFile << endl;<br />
        nRetCode = 1;<br />
      }<br />
<br />
      if (nRetCode==0)<br />
      {<br />
        cerr << _T("CXR created: ") << strOutFile << endl;<br />
      }<br />
    }<br />
    else<br />
    {<br />
      cerr << _T("Not enough parameters.") << endl;<br />
      cerr << _T("Usage: CXR -i [filename.cpp] -o [filename.cpp]") << endl;<br />
      nRetCode = 1;<br />
    }<br />
  }      <br />
  else<br />
  {<br />
    cerr << _T("Not enough parameters.") << endl;<br />
    cerr << _T("Usage: CXR -i [filename.cpp] -o [filename.cpp]") << endl;<br />
    nRetCode = 1;<br />
  }<br />
<br />
  return nRetCode;<br />
}<br />
<br />
<br />
///////////////////////////////////////////////////////////////////////////////<br />
// ProcessFile - Process a .CXR file (containing plaintext string literals)<br />
//               into C++ source files (containing the encrypted equivalent <br />
//               strings).<br />
//<br />
bool ProcessFile(ifstream &in, const string &strInFilename, ofstream &out, const string &strOutFilename)<br />
{<br />
  // Note: do not use TCHAR or _T() here. Do this all with single-byte char <br />
  // and string only, because we are writing source code here and source code<br />
  // is ANSI text.<br />
<br />
  enum {eStateWantPassword, eStateHavePassword, };<br />
<br />
  int iState = eStateWantPassword;<br />
<br />
  string strPassword;<br />
  string strLine;<br />
<br />
  char* pMetachars = "/\\=();'";<br />
  char* pKeyWords[3] = {"//", "_CXR", "CXRP"};<br />
<br />
  CTokenizer tokenizer(pKeyWords, 3, pMetachars, (int)strlen(pMetachars));<br />
  int iErr = CTokenizer::eErrorNone;<br />
  bool ok = true;<br />
<br />
  out << "/////////////////////////////////////////////////////////////\n"<br />
      << "// "<br />
      << strOutFilename<br />
      << "\n//\n"<br />
      << "// This file was generated by CXR, the literal string encryptor.\n"<br />
      << "// CXR, Copyright 2002, Smaller Animals Software, Inc., all rights reserved.\n"<br />
      << "//\n"<br />
      << "// Please do not edit this file. Any changes here will be overwritten on the next compile.\n// If you wish to make changes to a string, please edit:\n//     "<br />
      << strInFilename<br />
      <<"\n//\n"<br />
      << "\n/////////////////////////////////////////////////////////////\n\n"<br />
      << "#include \"stdafx.h\"\n"<br />
      << "#include \"cxr_inc.h\"\n\n";<br />
<br />
  bool bFoundCXR = false;<br />
<br />
  do <br />
  {<br />
    if(in.eof())<br />
      break;<br />
    else<br />
      getline(in, strLine);<br />
<br />
    if (in.bad() || in.fail())<br />
      break;<br />
<br />
    switch (iState)<br />
    {<br />
    case eStateWantPassword:<br />
      iErr = tokenizer.Tokenize(strLine.c_str());<br />
      if (iErr == CTokenizer::eErrorNone)<br />
      {<br />
        if (tokenizer.GetTokenCount() >= 4)<br />
        {<br />
          // password declaration always looks like : // CXRP = "Password"<br />
          if ((tokenizer.GetToken(0).strToken == "//") && <br />
              (tokenizer.GetToken(1).strToken == "CXRP") && <br />
              (tokenizer.GetToken(2).strToken == "=") && <br />
              (tokenizer.GetToken(3).bIsQuotedString))<br />
          {<br />
            // We'll use the password from the file, literally. it's not treated as<br />
            // a C string-literal, just as a section of a text file. when we<br />
            // go to write the decoder, we'll have to fix it up to make sure<br />
            // the compiler gets the same text by adding any necessary escapes.<br />
            strPassword = tokenizer.GetToken(3).strToken;<br />
<br />
            if (strPassword.empty())<br />
            {<br />
              cerr << _T("Invalid CXR password: \"") << strPassword.c_str() << _T("\"") << endl;  //TODO: not gonna work in Unicode builds?<br />
              //ASSERT(0);<br />
              break;<br />
            }<br />
<br />
            iState = eStateHavePassword;<br />
            continue;<br />
          }<br />
        }<br />
      }<br />
      break;<br />
    case eStateHavePassword:<br />
      bFoundCXR = false;<br />
      iErr = tokenizer.Tokenize(strLine.c_str());<br />
      if (iErr == CTokenizer::eErrorNone)<br />
      {<br />
        if (tokenizer.GetTokenCount() > 4)<br />
        {<br />
          for (int i=0; i < tokenizer.GetTokenCount() - 4; i++)<br />
          {<br />
            // looking for _CXR ( "..." )<br />
            if ((tokenizer.GetToken(i).strToken == "_CXR") && !tokenizer.GetToken(i).bIsQuotedString &&<br />
                (tokenizer.GetToken(i + 1).strToken == "(") && !tokenizer.GetToken(i + 1).bIsQuotedString &&<br />
                (tokenizer.GetToken(i + 2).bIsQuotedString) &&<br />
                (tokenizer.GetToken(i + 3).strToken == ")") && !tokenizer.GetToken(i + 3).bIsQuotedString)<br />
            {<br />
              string strTrans = TranslateString(tokenizer.GetToken(i + 2).strToken);<br />
              string strEnc = Encrypt(strTrans, strPassword.c_str());<br />
              //string strDec = Decrypt(strEnc, strPassword.c_str()); //for debugging<br />
<br />
              out << "///////////////////////////\n#ifdef _USING_CXR\n";<br />
<br />
              //out << "//" << strDec << "\n";<br />
<br />
              // output up to _CXR<br />
              out << strLine.substr(0, tokenizer.GetToken(i).iStart);<br />
<br />
              // encrypted stuff<br />
              out << "\"" << strEnc << "\"";<br />
<br />
              // to the end of the line<br />
              out << strLine.substr(tokenizer.GetToken(i + 4).iStop)<br />
                  << "\n"<br />
                  << "#else\n"<br />
                  << strLine<br />
                  << "\n#endif\n\n";<br />
<br />
              bFoundCXR = true;<br />
<br />
              break;<br />
            } // found a good string ?<br />
          } // loop over tokens<br />
        } // > 4 tokens<br />
      } // tokenizer OK<br />
<br />
      if (bFoundCXR)<br />
      {<br />
        continue;<br />
      }<br />
<br />
      break;<br />
    } // switch<br />
<br />
    // done with it<br />
    out << strLine << "\n";<br />
  } while (1);<br />
<br />
  if (iState == eStateWantPassword)<br />
  {<br />
    cerr << _T("No password line found in input file") << endl;<br />
    return false;<br />
  }<br />
<br />
  //ASSERT(iState == eStateHavePassword);<br />
<br />
  // add the decoder functions<br />
  AddDecode(strPassword, out);<br />
<br />
  return true;<br />
}<br />
<br />
<br />
///////////////////////////////////////////////////////////////////////////////<br />
// AddEncByte - Take BYTE c, obscure it by adding a base value (?), and <br />
//              append it (its value in hex characters) to string strOut<br />
//<br />
void AddEncByte(BYTE c, string &strOut)<br />
{<br />
  char buf[4];<br />
<br />
  BYTE b1 = c >> 4;<br />
  BYTE b2 = c & 0x0f;<br />
<br />
  _snprintf(buf, 3, "%x", b1 + basechar1);<br />
  strOut += "\\x";<br />
  strOut += buf;<br />
<br />
  _snprintf(buf, 3, "%x", b2 + basechar1);<br />
  strOut += "\\x";<br />
  strOut += buf;<br />
}<br />
<br />
<br />
///////////////////////////////////////////////////////////////////////////////<br />
// Encrypt - Given plaintext string strIn, encrypt it using password pPass<br />
//           and return it as a string of ciphertext.<br />
//<br />
string Encrypt(const string &strIn, const char* pPass)<br />
{<br />
  string strOut;<br />
<br />
  // initialize out <br />
  CCXRIntEnc sap((const BYTE*)pPass, (int)strlen(pPass));<br />
<br />
  //start each string with a random char.<br />
  //because this is a stream cipher, the ciphertext of a<br />
  //string like "ABC" will be the same as the first 3 bytes<br />
  //of the ciphertext for "ABCDEFG". <br />
<br />
  //by starting with a random value, the cipher will be in a <br />
  //different state (255:1) when it starts the real text. the<br />
  //decoder will simply discard the first plaintext byte.<br />
<br />
  BYTE seed = rand() % 256;<br />
  BYTE c = sap.ProcessByte((BYTE)(seed));<br />
  AddEncByte(c, strOut);<br />
<br />
  // Ok, now encrypt and convert strIn to hex string:<br />
  for (int i=0; i < (int)strIn.length(); i++)<br />
  {<br />
    char temp = strIn.at(i);<br />
    BYTE c = sap.ProcessByte((BYTE)(temp));<br />
    AddEncByte(c, strOut);<br />
  }<br />
<br />
  return strOut;<br />
}<br />
<br />
<br />
///////////////////////////////////////////////////////////////////////////////<br />
// Decrypt - Given ciphertext string pIn, decrypt using password pPass and<br />
//           return as a plaintext string.<br />
//<br />
string Decrypt(const TCHAR* pIn, const char* pPass)<br />
{<br />
  string strOut;<br />
<br />
  CCXRIntDec sap((const BYTE*)pPass, (int)strlen(pPass));<br />
<br />
  int iLen = (int)strlen(pIn);<br />
<br />
  if (iLen > 2)<br />
  {<br />
    int iBufLen = (int)strlen(pIn);<br />
    if (iBufLen & 0x01)<br />
    {<br />
      cerr << _T("Illegal string length in Decrypt") << endl;<br />
      return pIn;<br />
    }<br />
<br />
    iBufLen /= 2;<br />
<br />
    for (int i=0; i < iBufLen; i++)<br />
    {<br />
      int b1 = pIn[i * 2] - basechar1;<br />
      int b2 = pIn[i * 2 + 1] - basechar2;<br />
      int c = (b1 << 4) | b2;<br />
<br />
      BYTE bc = sap.ProcessByte((BYTE)(c));<br />
<br />
      if (i>0)<br />
        strOut += (char)bc;<br />
    }<br />
  }<br />
<br />
  return strOut;<br />
}<br />
<br />
<br />
///////////////////////////////////////////////////////////////////////////////<br />
// AddDecode - Write to the output source file, the decryption routines<br />
//             necessary to decrypt the strings we have encrypted.<br />
//<br />
bool AddDecode(const string &strPassword, ofstream &out)<br />
{<br />
   out << "\n\n/////////////////////////////////////////////////////////////\n"<br />
       << "// CXR-generated decoder follows\n\n"<br />
       << "#include <algorithm>\n"<br />
       << "const char * __pCXRPassword = \"";<br />
<br />
   // the password that encrypted the text used the literal text from the file (non-escaped \ chars).<br />
   // we need to make sure that compiler sees the same text when it gets the passowrd. so,<br />
   // we must double any "\" chars, to prevent them from becoming C-style escapes.<br />
   out << EscapeString(strPassword.c_str()) << "\";\n";<br />
<br />
   out << "const int __iCXRDecBase1 = " << basechar1 << ";\nconst int __iCXRDecBase2 = " << basechar2 << ";\n\n";<br />
                <br />
  const char* szDecodingFunction = <br />
    "string __CXRDecrypt(const char* pIn)\n"\<br />
    "{\n"\<br />
    "  string x; char b[3]; b[2]=0;\n"\<br />
    "  CXRD sap((const BYTE*)__pCXRPassword, (int)strlen(__pCXRPassword));\n"\<br />
    "  int iLen = (int)strlen(pIn);\n"\<br />
    "  if (iLen > 2)\n"\<br />
    "  {\n"\<br />
    "    int ibl = (int)strlen(pIn);\n"\<br />
    "    if (ibl & 0x01)\n"\<br />
    "    {\n"\<br />
    /*"      ASSERT(!\"Illegal string length in Decrypt\");\n"\*/<br />
    "      return pIn;\n"\<br />
    "    }\n"\<br />
    "    ibl /= 2;\n"\<br />
    "    for (int i=0; i < ibl; i++)\n"\<br />
    "    {\n"\<br />
    "      int b1 = pIn[i*2] - __iCXRDecBase1; int b2 = pIn[i*2+1] - __iCXRDecBase2;\n"\<br />
    "      int c = (b1 << 4) | b2; char ch =(char)(sap.pb((BYTE)(c)));\n"\<br />
    "      if (i>0)\n"\<br />
    "        x += ch;\n"\<br />
    "    }\n"\<br />
    "  }\n"\<br />
    "  return x;\n"\<br />
    "}\n";<br />
 <br />
  const char* szStreamCipherFunction =<br />
    "class CCXR\n" \<br />
    "{\n" \<br />
    "protected:\n" \<br />
    "  CCXR(const BYTE* key, unsigned int ks)\n" \<br />
    "  {\n" \<br />
    "    int i;BYTE rs;unsigned kp;\n" \<br />
    "    for(i=0;i<256;i++)c[i]=i;kp=0;rs=0;for(i=255;i;i--)std::swap(c[i],c[kr(i,key,ks,&rs,&kp)]);r2=c[1];r1=c[3];av=c[5];lp=c[7];lc=c[rs];rs=0;kp=0;\n" \<br />
    "  }\n" \<br />
    "	 inline void SC(){BYTE st=c[lc];r1+=c[r2++];c[lc]=c[r1];c[r1]=c[lp];c[lp]=c[r2];c[r2]=st;av+=c[st];}\n" \<br />
    "	 BYTE c[256],r2,r1,av,lp,lc;    \n" \<br />
    "\n" \<br />
    "  BYTE kr(unsigned int lm, const BYTE *uk, BYTE ks, BYTE *rs, unsigned *kp)\n" \<br />
    "  {\n" \<br />
    "    unsigned rl=0,mk=1,u;while(mk<lm)mk=(mk<<1)+1;do{*rs=c[*rs]+uk[(*kp)++];if(*kp>=ks){*kp=0;*rs+=ks;}u=mk&*rs;if(++rl>11)u%=lm;}while(u>lm);return u;\n" \<br />
    "  }\n" \<br />
    "};\n" \<br />
    "struct CXRD:CCXR\n" \<br />
    "{\n" \<br />
    "	 CXRD(const BYTE *userKey, unsigned int keyLength=16) : CCXR(userKey, keyLength) {}\n" \<br />
    "	 inline BYTE pb(BYTE b){SC();lp=b^c[(c[r1]+c[r2])&0xFF]^c[c[(c[lp]+c[lc]+c[av])&0xFF]];lc=b;return lp;}\n" \<br />
    "};\n";<br />
<br />
  out << szStreamCipherFunction;<br />
  out << szDecodingFunction;<br />
<br />
  return true;<br />
}<br />
<br />
<br />
///////////////////////////////////////////////////////////////////////////////<br />
// TranslateString - Translate C-style string escapes as documented in K&R<br />
//                   2nd, A2.5.2<br />
//<br />
string TranslateString(const string &strIn)<br />
{<br />
  string strOut;<br />
<br />
  for (int i=0; i < (int)strIn.length(); i++)<br />
  {<br />
    int c = strIn.at(i); //TODO: Why even treat this as an int? Why not just char?<br />
    switch (c)<br />
    {<br />
      // normal text<br />
      default:<br />
        strOut += static_cast<char>(c);<br />
        break;<br />
      <br />
      // c-style escape<br />
      case '\\':<br />
        if (i < (int)strIn.length() - 1)<br />
        {<br />
          c = strIn.at(i + 1);<br />
          switch (c)<br />
          {<br />
            case 'n':<br />
              strOut += '\n';<br />
              break;<br />
            case 't':<br />
              strOut += '\t';<br />
              break;<br />
            case 'v':<br />
              strOut += '\v';<br />
              break;<br />
            case 'b':<br />
              strOut += '\b';<br />
              break;<br />
            case 'r':<br />
              strOut += '\r';<br />
              break;<br />
            case 'f':<br />
              strOut += '\f';<br />
              break;<br />
            case 'a':<br />
              strOut += '\a';<br />
              break;<br />
            case '\\':<br />
              strOut += '\\';<br />
              break;<br />
            case '?':<br />
              strOut += '?';<br />
              break;<br />
            case '\'':<br />
              strOut += '\'';<br />
              break;<br />
            case '\"':<br />
              strOut += '\"';<br />
              break;<br />
            case '0':<br />
            case '1':<br />
            case '2':<br />
            case '3':<br />
            case '4':<br />
            case '5':<br />
            case '6':<br />
            case '7':<br />
              {<br />
                // expand octal<br />
                int iConsumed = 0;<br />
                if (!ExpandOctal(strIn.substr(i), strOut, iConsumed))<br />
                {<br />
                  cerr << _T("Invalid octal sequence: ") << _T('\"') << strIn.c_str() << _T('\"') << endl; //TODO: Not gonna work in Unicode builds?<br />
                  strOut = strIn;<br />
                  break;<br />
                }<br />
                i += iConsumed - 1;<br />
              }<br />
              break;<br />
            case 'x':<br />
              { <br />
                // expand hex<br />
                int iConsumed = 0;<br />
                if (!ExpandHex(strIn.substr(i), strOut, iConsumed))<br />
                {<br />
                  cerr << _T("Invalid hex sequence: ") << _T('\"') << strIn.c_str() << _T('\"') << endl; //TODO: Not gonna work in Unicode builds?<br />
                  strOut = strIn;<br />
                  break;<br />
                }<br />
                i += iConsumed - 1;<br />
              }<br />
              break;<br />
          }<br />
<br />
          i++;<br />
          continue;<br />
        }<br />
        else<br />
        {<br />
          cerr << _T("Invalid escape sequence: ") << _T('\"') << strIn.c_str() << _T('\"') << endl; //TODO: Not gonna work in Unicode builds?<br />
          strOut = strIn;<br />
          break;<br />
        }<br />
      break;<br />
    }<br />
  }<br />
<br />
  return strOut;<br />
}<br />
<br />
<br />
///////////////////////////////////////////////////////////////////////////////<br />
// ExpandOctal<br />
//<br />
bool ExpandOctal(const string &strIn, string &strOut, int &iConsumed)<br />
{<br />
  // starting with the escape, we need at least one more char<br />
  if (strIn.length() < 2)<br />
    return false;<br />
<br />
  if (strIn.at(0) != '\\')<br />
    return false;<br />
<br />
  int iStart = 1;<br />
  int iCur = iStart;<br />
<br />
  string strDigits;<br />
  int c = strIn.at(iCur);  //TODO: again, why represent it with an int?<br />
  while ((c >= '0') && (c <= '7'))<br />
  {<br />
    strDigits += static_cast<char>(c);<br />
<br />
    // An escape can't hold more that 3 octal digits (K&R 2nd A2.5.2)<br />
    if (iCur == 3)<br />
      break;<br />
         <br />
    iCur++;<br />
    c = strIn.at(iCur);<br />
  }<br />
<br />
  char* end;<br />
  int octval = (char)strtol(strDigits.c_str(), &end, 8);<br />
<br />
  iConsumed = (int)strDigits.length();<br />
<br />
  strOut += static_cast<char>(octval);<br />
<br />
  return true;<br />
}<br />
<br />
<br />
///////////////////////////////////////////////////////////////////////////////<br />
// ExpandHex<br />
//<br />
bool ExpandHex(const string &strIn, string &strOut, int &iConsumed)<br />
{<br />
  // Starting with the escape and the 'x', we need at least one more char<br />
  if (strIn.length() < 3)<br />
    return false;<br />
<br />
  if ((strIn.at(0) != _T('\\')) || (strIn.at(1) != _T('x')))<br />
    return false;<br />
<br />
  int iStart = 2;<br />
  int iCur = iStart;<br />
<br />
  string strDigits;<br />
  int c = strIn.at(iCur);<br />
  while (_istxdigit(c))<br />
  {<br />
    strDigits += static_cast<char>(c);<br />
<br />
    iCur++;<br />
    c = strIn.at(iCur);<br />
  }<br />
<br />
  char* end;<br />
<br />
  // "There is no limit on the number of digits, but the behavior is undefined<br />
  // if the resulting character value exceeds that of the largest character"<br />
  // (K&R 2nd A2.5.2)<br />
  int hex = (char)strtol(strDigits.c_str(), &end, 16);<br />
<br />
  iConsumed = (int)strDigits.length();<br />
<br />
  iConsumed++;  // count the "x"<br />
<br />
  strOut += static_cast<char>(hex);<br />
<br />
  return true;<br />
}<br />
<br />
<br />
///////////////////////////////////////////////////////////////////////////////<br />
// EscapeString<br />
//<br />
string EscapeString(const char* pIn)<br />
{<br />
  string strOut;<br />
<br />
  int iLen = (int)strlen(pIn);<br />
<br />
  for (int i=0; i < iLen; i++)<br />
  {<br />
    strOut += pIn[i];<br />
    <br />
    // Double all "\" chars<br />
    if (pIn[i] == '\\')<br />
    {<br />
      strOut += '\\';<br />
    }<br />
  }<br />
<br />
  return strOut;<br />
}<br />


Tokenizer.cpp:
<br />
/*********************************************************************<br />
<br />
   Copyright (C) 2002 Smaller Animals Software, Inc.<br />
<br />
   This software is provided 'as-is', without any express or implied<br />
   warranty.  In no event will the authors be held liable for any damages<br />
   arising from the use of this software.<br />
<br />
   Permission is granted to anyone to use this software for any purpose,<br />
   including commercial applications, and to alter it and redistribute it<br />
   freely, subject to the following restrictions:<br />
<br />
   1. The origin of this software must not be misrepresented; you must not<br />
     claim that you wrote the original software. If you use this software<br />
     in a product, an acknowledgment in the product documentation would be<br />
     appreciated but is not required.<br />
<br />
   2. Altered source versions must be plainly marked as such, and must not be<br />
     misrepresented as being the original software.<br />
<br />
   3. This notice may not be removed or altered from any source distribution.<br />
<br />
   http://www.smalleranimals.com<br />
   smallest@smalleranimals.com<br />
<br />
**********************************************************************/<br />
<br />
// Tokenizer.cpp: implementation of the CTokenizer class.<br />
//<br />
//////////////////////////////////////////////////////////////////////<br />
<br />
#include "stdafx.h"<br />
#include "Tokenizer.h"<br />
<br />
// CXR does not have comments<br />
#undef ALLOW_COMMENTS<br />
<br />
// strip quotes on strings, please<br />
#undef RETURN_QUOTED_STRINGS<br />
<br />
#ifdef ALLOW_COMMENTS<br />
#define COMMENT_START   "/*"<br />
#define COMMENT_STOP    "*/"<br />
#endif<br />
<br />
//////////////////////////////////////////////////////////////////////<br />
// Construction/Destruction<br />
//<br />
CTokenizer::CTokenizer(char** pKeyWords, int iKeyWords, char* pMetaChars, int iMetaChars)<br />
{<br />
  m_pKeyWords = pKeyWords;<br />
  m_iKeyWords = iKeyWords;<br />
  m_MetaChars = pMetaChars;<br />
  m_iMetaChars = iMetaChars;<br />
}<br />
<br />
CTokenizer::~CTokenizer()<br />
{<br />
}<br />
<br />
<br />
//////////////////////////////////////////////////////////////////////<br />
// CTokenizer::Clear() - Remove tokens<br />
//<br />
void CTokenizer::Clear()<br />
{<br />
  m_tokens.clear();<br />
}<br />
<br />
<br />
void CTokenizer::Init()<br />
{<br />
  Clear();<br />
}<br />
<br />
<br />
//////////////////////////////////////////////////////////////////////<br />
// CTokenizer::Tokenize - Extract an array of tokens from input text<br />
//<br />
int CTokenizer::Tokenize(const char* pInputLine)<br />
{<br />
  int err = eErrorNone;<br />
<br />
  Init();<br />
<br />
  int iLen = (int)strlen(pInputLine);<br />
<br />
  bool bInComment = false;<br />
<br />
  for (int i=0; i < iLen; i++)<br />
  {<br />
    string curTokenString;<br />
    bool bQuotedString = false;<br />
<br />
    int iConsumed = GetToken(pInputLine + i, curTokenString, bQuotedString);<br />
<br />
    if (iConsumed > 0)<br />
    {<br />
      //if (curTokenString.length() > 0)<br />
      {<br />
#ifdef ALLOW_COMMENTS<br />
        if (curTokenString == COMMENT_START)<br />
        {<br />
          bInComment = true;<br />
          i+=iConsumed;<br />
          continue;<br />
        }<br />
            <br />
        if (curTokenString == COMMENT_STOP)<br />
        {<br />
          if (!bInComment)<br />
          {<br />
            err = eErrorSyntax;<br />
            break;<br />
          }<br />
<br />
          bInComment = false;<br />
<br />
          i += iConsumed;<br />
          continue;<br />
        }<br />
#endif<br />
<br />
        if (!bInComment)<br />
        {<br />
          int iStart = i;<br />
          int iStop = i + iConsumed - 1;<br />
<br />
          CSAToken curToken(curTokenString.c_str(), iStart, iStop, bQuotedString);<br />
<br />
          m_tokens.push_back(curToken);<br />
        }<br />
      }<br />
         <br />
      i += iConsumed;<br />
<br />
      i--;  // back up! the for iteration will increase i<br />
      continue;<br />
    }<br />
    else<br />
    {<br />
      if (IsMetaChar(*(pInputLine + i)))<br />
      {<br />
        if (!isspace(*(pInputLine + i)))<br />
        {<br />
          curTokenString.clear();<br />
          curTokenString += *(pInputLine + i);<br />
<br />
          CSAToken curToken(curTokenString.c_str(), i, (int)curTokenString.length() - 1, bQuotedString);<br />
<br />
          m_tokens.push_back(curToken);<br />
        }<br />
      }<br />
    }<br />
  }<br />
<br />
  return err;<br />
}<br />
<br />
<br />
//////////////////////////////////////////////////////////////////////<br />
// CTokenizer::IsKeyWord - Asks: is this text a keyword?<br />
//<br />
bool CTokenizer::IsKeyWord(string &str)<br />
{<br />
  return IsKeyWord((const char*)str.c_str());<br />
}<br />
<br />
<br />
//////////////////////////////////////////////////////////////////////<br />
// CTokenizer::IsKeyWord<br />
//<br />
bool CTokenizer::IsKeyWord(const char* pInput)<br />
{<br />
  if (m_pKeyWords==NULL)<br />
  {<br />
    return false;<br />
  }<br />
<br />
  int iLen = (int)strlen(pInput);<br />
<br />
  int iBestMatch = -1;<br />
<br />
  for (int i=0; i < m_iKeyWords; i++)<br />
  {<br />
    int iCurKWLen = (int)strlen(m_pKeyWords[i]);<br />
<br />
    if (iLen <= iCurKWLen)<br />
    {<br />
      if (strnicmp(m_pKeyWords[i], pInput, iCurKWLen)==0)<br />
      {<br />
        iBestMatch = i;<br />
      }<br />
    }<br />
  }<br />
<br />
  if (iBestMatch==-1)<br />
  {<br />
#ifdef ALLOW_COMMENTS<br />
    if (CSAScrUtil::sa_strnicmp(COMMENT_START, pInput, strlen(COMMENT_START))==0)<br />
    {<br />
      iBestMatch = m_iKeyWords + 1;<br />
    }<br />
<br />
    if (CSAScrUtil::sa_strnicmp(COMMENT_STOP, pInput, strlen(COMMENT_STOP))==0)<br />
    {<br />
      iBestMatch = m_iKeyWords + 2;<br />
    }<br />
#endif<br />
  }<br />
  return (iBestMatch != -1);<br />
}<br />
<br />
<br />
//////////////////////////////////////////////////////////////////////<br />
// CTokenizer::GetToken - find the next token in the string<br />
//<br />
int CTokenizer::GetToken(const char* pInput, string &out, bool &bQuotedString)<br />
{<br />
  int iLen = (int)strlen(pInput);<br />
<br />
  bool bFoundChars = false;<br />
<br />
  bool bScanningMetaKW = false;<br />
<br />
  bool bInQuotes = false;<br />
<br />
  bQuotedString = false;<br />
<br />
  char c;<br />
<br />
  for (int iWS = 0; iWS < iLen; iWS++)<br />
  {<br />
    c = *(pInput + iWS);<br />
    if (!isspace(c))<br />
      break;<br />
    if (!iscntrl(c))<br />
      break;<br />
  }<br />
<br />
  for (int i=iWS; i<iLen; i++)<br />
  {<br />
    c = *(pInput + i);<br />
<br />
    // not in quotes?<br />
    // open quote<br />
    if ((c == '"') && !bInQuotes)<br />
    {<br />
      // not in quotes, but we found a ", and we've already found chars?<br />
      if (bFoundChars)<br />
      {<br />
        break;<br />
      }<br />
<br />
      bInQuotes = true;<br />
#ifdef RETURN_QUOTED_STRINGS<br />
      out+=c;<br />
#endif<br />
      continue;<br />
    }<br />
<br />
    // close quote<br />
    if ((c == '"') && bInQuotes)<br />
    {<br />
      bInQuotes = false;<br />
#ifdef RETURN_QUOTED_STRINGS<br />
      out += c;<br />
#endif<br />
      i += 1;<br />
<br />
      bQuotedString = true;<br />
      break;<br />
    }<br />
<br />
    if (bInQuotes)<br />
    {<br />
      // escape!<br />
      if (c == '\\')<br />
      {<br />
        if (i < iLen - 1)<br />
        {<br />
          switch (*(pInput + i + 1))<br />
          {<br />
            // if we see \" in a quoted string, don't treat it as a string end!<br />
            case '"':<br />
              out += "\\\""; // output the backslash and the quote<br />
              i++; // skip the quote in the string<br />
              continue;<br />
              break;<br />
               <br />
            default:<br />
              // don't touch the other escapes.<br />
              out += c;<br />
              continue;<br />
              break;<br />
          }<br />
        }<br />
      }<br />
<br />
      out += c;<br />
      continue;<br />
    }<br />
<br />
    // break non-quoted strings on ctrl or white space<br />
    if (iscntrl(c) || isspace(c))<br />
    {<br />
      break;<br />
    }<br />
<br />
    // metachars...<br />
    if (IsMetaChar(c))<br />
    {<br />
      if (iscntrl(c) || isspace(c))<br />
      {<br />
        break;<br />
      }<br />
<br />
      if (!bFoundChars)<br />
      {<br />
        bScanningMetaKW = true;<br />
<br />
        bFoundChars = true;<br />
<br />
        // in case some KWs start with metachars<br />
        if (i < iLen - 2)<br />
        {<br />
          char buf[3];<br />
          buf[0] = c;<br />
          buf[1] = *(pInput + i + 1);<br />
          buf[2] = 0;<br />
<br />
          if (IsKeyWord(buf))<br />
          {<br />
            out += c;<br />
            out += *(pInput + i + 1);<br />
<br />
            i += 2;<br />
<br />
            break;<br />
          }<br />
          else<br />
          {<br />
            buf[1] = 0;<br />
            if (IsKeyWord(buf))<br />
            {<br />
              out += c;<br />
<br />
              i += 1;<br />
<br />
              break;<br />
            }<br />
          }<br />
        }<br />
<br />
        out += c;<br />
      }<br />
      else<br />
      {<br />
        break;<br />
      }<br />
    }<br />
    else<br />
    {<br />
      if (!bFoundChars)<br />
      {<br />
        bScanningMetaKW = false;<br />
<br />
        bFoundChars = true;<br />
<br />
        out += c;<br />
      }<br />
      else<br />
      {<br />
        if (bScanningMetaKW)<br />
        {<br />
          break;<br />
        }<br />
        else<br />
        {<br />
          out += c;<br />
        }<br />
      }<br />
    }<br />
  }<br />
<br />
  return i;<br />
}<br />
<br />
<br />
//////////////////////////////////////////////////////////////////////<br />
// CTokenizer::IsMetaChar<br />
//<br />
bool CTokenizer::IsMetaChar(const char c)<br />
{<br />
  for (int i=0; i < m_iMetaChars; i++)<br />
  {<br />
    if (c == m_MetaChars[i])<br />
      return true;<br />
  }<br />
<br />
  return false;<br />
}<br />
<br />
<br />
//////////////////////////////////////////////////////////////////////<br />
// CTokenizer::IsMetaChar<br />
//<br />
bool CTokenizer::IsMetaChar(string &str)<br />
{<br />
  if (str.length() > 1)<br />
    return false;<br />
<br />
  char c = str.at(0);<br />
<br />
  for (int i=0; i < m_iMetaChars; i++)<br />
  {<br />
    if (c == m_MetaChars[i])<br />
      return true;<br />
  }<br />
<br />
  return false;<br />
}<br />
<br />
<br />
//////////////////////////////////////////////////////////////////////<br />
// CTokenizer::Dump<br />
//<br />
void CTokenizer::Dump()<br />
{<br />
  CSATokenVector::iterator theIterator;<br />
<br />
  int i=0;<br />
  for (theIterator = m_tokens.begin(); theIterator < m_tokens.end(); theIterator++)<br />
  {<br />
    //If you're interested in debug output, re-implement this to suit you:<br />
    //TRACE("%d [%d-%d] : \"%s\"\n", i++, (*theIterator).iStart, (*theIterator).iStop, (const TCHAR *)((*theIterator).csToken));<br />
  }<br />
}<br />
<br />
<br />
//////////////////////////////////////////////////////////////////////<br />
// Operator overloading<br />
//<br />
bool operator < (const CSAToken &a, const CSAToken &b)<br />
{<br />
  return (a.iStart < b.iStart);<br />
}<br />
<br />
bool operator == (const CSAToken &a, const CSAToken &b)<br />
{<br />
  return (a.iStart == b.iStart);<br />
}<br />


cxr_inc.h:
<br />
/*********************************************************************<br />
<br />
   Copyright (C) 2002 Smaller Animals Software, Inc.<br />
<br />
   This software is provided 'as-is', without any express or implied<br />
   warranty.  In no event will the authors be held liable for any damages<br />
   arising from the use of this software.<br />
<br />
   Permission is granted to anyone to use this software for any purpose,<br />
   including commercial applications, and to alter it and redistribute it<br />
   freely, subject to the following restrictions:<br />
<br />
   1. The origin of this software must not be misrepresented; you must not<br />
     claim that you wrote the original software. If you use this software<br />
     in a product, an acknowledgment in the product documentation would be<br />
     appreciated but is not required.<br />
<br />
   2. Altered source versions must be plainly marked as such, and must not be<br />
     misrepresented as being the original software.<br />
<br />
   3. This notice may not be removed or altered from any source distribution.<br />
<br />
   http://www.smalleranimals.com<br />
   smallest@smalleranimals.com<br />
<br />
**********************************************************************/<br />
#pragma once<br />
<br />
#include <string><br />
<br />
using namespace std;<br />
<br />
#define _USING_CXR<br />
<br />
#ifndef _USING_CXR<br />
  #define _CXR(x) x<br />
#else<br />
  #define _CXR(x) __CXRDecrypt(x)<br />
  extern string __CXRDecrypt(const char* pIn);<br />
#endif<br />


stdafx.h:
<br />
// stdafx.h : include file for standard system include files,<br />
// or project specific include files that are used frequently, but<br />
// are changed infrequently<br />
//<br />
<br />
#pragma once<br />
<br />
<br />
#include <iostream><br />
#include <tchar.h><br />
<br />
// TODO: reference additional headers your program requires here<br />
<br />


Stream.h:
<br />
/*********************************************************************<br />
<br />
   Copyright (C) 2002 Smaller Animals Software, Inc.<br />
<br />
   This software is provided 'as-is', without any express or implied<br />
   warranty.  In no event will the authors be held liable for any damages<br />
   arising from the use of this software.<br />
<br />
   Permission is granted to anyone to use this software for any purpose,<br />
   including commercial applications, and to alter it and redistribute it<br />
   freely, subject to the following restrictions:<br />
<br />
   1. The origin of this software must not be misrepresented; you must not<br />
     claim that you wrote the original software. If you use this software<br />
     in a product, an acknowledgment in the product documentation would be<br />
     appreciated but is not required.<br />
<br />
   2. Altered source versions must be plainly marked as such, and must not be<br />
     misrepresented as being the original software.<br />
<br />
   3. This notice may not be removed or altered from any source distribution.<br />
<br />
   http://www.smalleranimals.com<br />
   smallest@smalleranimals.com<br />
<br />
**********************************************************************/<br />
/*<br />
	modified by Chris Losinger for Smaller Animals Software, Inc.<br />
*/<br />
// Sapphire.cpp -- modified by Wei Dai from:<br />
<br />
/* Sapphire.cpp -- the Saphire II stream cipher class.<br />
   Dedicated to the Public Domain the author and inventor:<br />
   (Michael Paul Johnson).  This code comes with no warranty.<br />
   Use it at your own risk.<br />
   Ported from the Pascal implementation of the Sapphire Stream<br />
   Cipher 9 December 1994.<br />
   Added hash pre- and post-processing 27 December 1994.<br />
   Modified initialization to make index variables key dependent,<br />
   made the output function more resistant to cryptanalysis,<br />
   and renamed to CPASapphire II 2 January 1995<br />
*/<br />
<br />
#pragma once<br />
<br />
typedef unsigned char BYTE;<br />
<br />
class CCXRIntBase<br />
{<br />
protected:<br />
   CCXRIntBase(const BYTE* key, unsigned int ks)<br />
   {<br />
      int i;BYTE rs;unsigned kp;<br />
      for(i=0;i<256;i++)c[i]=i;kp=0;rs=0;for(i=255;i;i--)std::swap(c[i],c[kr(i,key,ks,&rs,&kp)]);r2=c[1];r1=c[3];av=c[5];lp=c[7];lc=c[rs];rs=0;kp=0;<br />
   }<br />
	inline void SC(){BYTE st=c[lc];r1+=c[r2++];c[lc]=c[r1];c[r1]=c[lp];c[lp]=c[r2];c[r2]=st;av+=c[st];}<br />
	BYTE c[256],r2,r1,av,lp,lc;    <br />
<br />
   BYTE kr(unsigned int lm, const BYTE *uk, BYTE ks, BYTE *rs, unsigned *kp)<br />
   {<br />
      unsigned rl=0,mk=1,u;<br />
      while(mk<lm)mk=(mk<<1)+1;<br />
      do{*rs=c[*rs]+uk[(*kp)++];<br />
      if(*kp>=ks){*kp=0;*rs+=ks;}u=mk&*rs;<br />
      if(++rl>11)u%=lm;}while(u>lm);<br />
      return u;<br />
   }<br />
};<br />
<br />
<br />
struct CCXRIntDec:CCXRIntBase<br />
{<br />
	CCXRIntDec(const BYTE *userKey, unsigned int keyLength=16) : CCXRIntBase(userKey, keyLength) {}<br />
	inline BYTE ProcessByte(BYTE b){SC();lp=b^c[(c[r1]+c[r2])&0xFF]^c[c[(c[lp]+c[lc]+c[av])&0xFF]];lc=b;return lp;}<br />
};<br />
<br />
<br />
struct CCXRIntEnc:CCXRIntBase<br />
{<br />
	CCXRIntEnc(const BYTE *userKey, unsigned int keyLength=16) : CCXRIntBase(userKey, keyLength) {}<br />
	inline BYTE ProcessByte(BYTE b){SC();lc=b^c[(c[r1]+c[r2])&0xFF]^c[c[(c[lp]+c[lc]+c[av])&0xFF]];lp=b;return lc;}<br />
};<br />


Tokenizer.h:
<br />
/*********************************************************************<br />
<br />
   Copyright (C) 2002 Smaller Animals Software, Inc.<br />
<br />
   This software is provided 'as-is', without any express or implied<br />
   warranty.  In no event will the authors be held liable for any damages<br />
   arising from the use of this software.<br />
<br />
   Permission is granted to anyone to use this software for any purpose,<br />
   including commercial applications, and to alter it and redistribute it<br />
   freely, subject to the following restrictions:<br />
<br />
   1. The origin of this software must not be misrepresented; you must not<br />
     claim that you wrote the original software. If you use this software<br />
     in a product, an acknowledgment in the product documentation would be<br />
     appreciated but is not required.<br />
<br />
   2. Altered source versions must be plainly marked as such, and must not be<br />
     misrepresented as being the original software.<br />
<br />
   3. This notice may not be removed or altered from any source distribution.<br />
<br />
   http://www.smalleranimals.com<br />
   smallest@smalleranimals.com<br />
<br />
**********************************************************************/<br />
<br />
#pragma once<br />
<br />
#include <vector><br />
#include <iterator><br />
<br />
#pragma warning(disable:4786)<br />
using namespace std ;<br />
using namespace std::rel_ops ;<br />
<br />
//////////////////////////////////////////////////////////////////////<br />
<br />
class CSAToken <br />
{<br />
public:<br />
  CSAToken()<br />
  {<br />
    iStart = iStop = -1;<br />
    bIsQuotedString = false;<br />
  }<br />
   <br />
  CSAToken(const char* p, int x, int y, bool q)<br />
  {<br />
    strToken = p;<br />
    iStart = x;<br />
    iStop = y;<br />
    //ASSERT(x <= y);<br />
<br />
    bIsQuotedString = q;<br />
  }<br />
<br />
  string  strToken;<br />
  int     iStart;<br />
  int     iStop;<br />
  bool    bIsQuotedString;<br />
};<br />
<br />
//////////////////////////////////////////////////////////////////////<br />
<br />
typedef vector<CSAToken> CSATokenVector;<br />
<br />
//////////////////////////////////////////////////////////////////////<br />
<br />
class CTokenizer  <br />
{<br />
public:<br />
  enum {eErrorNone, eErrorSyntax,}eError;<br />
<br />
  CTokenizer(char** pKeyWords, int iKeyWords, char* pMetaChars, int iMetaChars);<br />
  virtual ~CTokenizer();<br />
  void    Clear();<br />
  void    Init();<br />
<br />
  int     Tokenize(const char* pInputLine);<br />
   <br />
  bool    IsKeyWord(string &str);<br />
  bool    IsKeyWord(const char* pInput);<br />
<br />
  void    Dump();<br />
   <br />
  bool    IsMetaChar(const char c); <br />
  bool    IsMetaChar(string &str);<br />
<br />
  _inline int      GetTokenCount()   {return (int)m_tokens.size();}<br />
  _inline CSAToken GetToken(int i)   {return m_tokens.at(i);}<br />
<br />
protected:<br />
  int     GetToken(const char* pInput, string &out, bool &bQuotedString);<br />
   <br />
  char**  m_pKeyWords;<br />
  int     m_iKeyWords;<br />
  char*   m_MetaChars;<br />
  int     m_iMetaChars;<br />
<br />
  CSATokenVector m_tokens;<br />
};<br />
<br />
//////////////////////////////////////////////////////////////////////<br />
<br />
extern bool operator < (const CSAToken &a, const CSAToken &b);<br />
extern bool operator == (const CSAToken &a, const CSAToken &b);<br />

GeneralRe: Things I had to change to compile CXR Pin
ichscheissdirinsgsichthey11-Sep-06 6:20
ichscheissdirinsgsichthey11-Sep-06 6:20 
GeneralThanks, and improvements Pin
Boniolopez18-Jan-06 7:16
Boniolopez18-Jan-06 7:16 
GeneralRe: Thanks, and improvements Pin
Hokei2-Mar-06 9:24
Hokei2-Mar-06 9:24 
GeneralRe: Thanks, and improvements Pin
Boniolopez2-Mar-06 10:56
Boniolopez2-Mar-06 10:56 
GeneralCXR for Linux Pin
John McGehee6-May-05 20:25
John McGehee6-May-05 20:25 
GeneralRe: CXR for Linux Pin
Hokei14-Mar-06 20:45
Hokei14-Mar-06 20:45 
GeneralRe: CXR for Linux Pin
paleozogt13-Jan-10 5:59
paleozogt13-Jan-10 5:59 
Generalcool Pin
Proxy4NT12-Apr-05 2:09
Proxy4NT12-Apr-05 2:09 
GeneralYou can do (very) basic xor encryption with the preprocessors Pin
MB_OK17-Mar-05 20:39
MB_OK17-Mar-05 20:39 
GeneralRe: You can do (very) basic xor encryption with the preprocessors Pin
MB_OK17-Mar-05 20:58
MB_OK17-Mar-05 20:58 
QuestionDoesn't work with \ at the end? Pin
mjimenez17-Mar-05 13:01
mjimenez17-Mar-05 13:01 
AnswerRe: Doesn't work with \ at the end? Pin
Chris Losinger17-Mar-05 14:59
professionalChris Losinger17-Mar-05 14:59 
GeneralSuggestion for obfuscated strings Pin
Michael Dunn5-Oct-02 18:30
sitebuilderMichael Dunn5-Oct-02 18:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.