// ================================================================
// Implements the password scrambling algorithm used by NX in C++
// as defined here:
//
// http://www.nomachine.com/ar/view.php?ar_id=AR01C00125
//
// Usage:
//    ./nxscramble.exe <password>
// ================================================================
#include <cstdio>
#include <ctime>
#include <string>
#include <iomanip>
#include <iostream>
using namespace std;

const int numValidCharList = 85;
const string dummyString = "{{{{";

string encodePassword(const string& p)
{
  string sPass = ":";
  string sTmp = "";

  if (p.empty()) {
    return "";
  }

  char buf[8];
  for (unsigned int i = 0; i < p.length(); i++) {
    char c = (char) p.at(i);
    sprintf(buf,"%d:", (c + i + 1));
    sTmp = buf;
    sPass += sTmp;
    sTmp = "";
  }

  return sPass;
}

namespace {
  char validCharList[numValidCharList] =
    {
      '!',  '#',  '$',  '%',  '&',  '(',  ')',  '*',  '+',  '-',
      '.',  '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',  '8',
      '9',  ':',  ';',  '<',  '>',  '?',  '@',  'A',  'B',  'C',
      'D',  'E',  'F',  'G',  'H',  'I',  'J',  'K',  'L',  'M',
      'N',  'O',  'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',
      'X',  'Y',  'Z',  '[',  ']',  '_',  'a',  'b',  'c',  'd',
      'e',  'f',  'g',  'h',  'i',  'j',  'k',  'l',  'm',  'n',
      'o',  'p',  'q',  'r',  's',  't',  'u',  'v',  'w',  'x',
      'y',  'z',  '{',  '|',  '}'
    };

  int findCharInList(char c)
  {
    int i = -1;
    
    for (int j = 0; j < numValidCharList; j++) {
      if (validCharList[j] == c) {
	i = j;
	return i;
      }
    }
    
    return i;
  }
  
  char getRandomValidCharFromList()
  {
    time_t raw;
    struct tm *ti;
    time(&raw);
    ti = localtime( &raw );
    int k = ti->tm_sec;
    return validCharList[k];
  }
}

string scrambleString(const string& s)
{
  string sRet = "";

  if (s.empty()) {
    return s;
  }

  string str = encodePassword(s);
  
  if (str.length() < 32) {
    str += dummyString;
  }

  for (int iR = (str.length() - 1); iR >= 0; iR--) {
    sRet += str.at(iR);
  }

  if (sRet.length() < 32) {
    sRet += dummyString;
  }

  int k = getRandomValidCharFromList();
  int l = k + sRet.length() - 2;

  char buf[8];
  sprintf(buf,"%c",k);
  sRet.insert(0, buf);

  for (int i1 = 1; i1 < (int)sRet.length(); i1++) {
    int j = findCharInList(sRet.at(i1));

    if (j == -1) {
      return sRet;
    }

    int i = (j + l * (i1 + 1)) % numValidCharList;
    sRet[i1] = validCharList[i];
  }

  char c = getRandomValidCharFromList() + 2;
  buf[0] = c;
  buf[1] = 0;
  sRet.append(buf);
  return sRet;
}

int main(int argc, char** argv)
{
  for(int i=1;i<argc;++i) {
    string in = argv[i];
    string out = scrambleString(in);
    if (i==1) {
      cout << out << endl;
    }
  }
  return 0;
}

