#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std;

typedef vector< string > args_type;

string
quote(const string & str) 
{
   string ret;
   for(size_t i = 0; i < str.size(); i++) {
      if(str[i] == '\"') {
         ret += "\"\"";
      }
      else {
         ret += str[i];
      }
   }
   return ret;
}

int
System(const string & cmd)
{
   return system(cmd.c_str());
}

class cab {
   void prep_file(const string& dir) {
      ifstream fin("cab-file-list.txt");
      if(fin) {
         char buffer[1024];
         memset(buffer, 0, 1024);
         fin.getline(buffer, 1023);
         vector< string > vec;
         while(fin) {
            vec.push_back(buffer);
            memset(buffer, 0, 1024);
            fin.getline(buffer, 1023);
         }
         fin.close();
         ofstream fout("cab2-file-list.txt", ios::ate | ios::trunc | ios::out);
         if(fout) {
            string d;
            string last;
            for(size_t i = 0; i < vec.size(); i++) {
               string & temp = vec[i];
               string::size_type ptr1 = temp.rfind(dir);
               if(ptr1 != string::npos) {
                  string the_dir = temp.substr(ptr1);
                  string::size_type ptr2 = the_dir.rfind("\\");
                  if(ptr2 != string::npos) {
                     the_dir = the_dir.substr(0,ptr2);
                     if(last != the_dir) {
                        fout << ".Set DestinationDir=" << the_dir << endl;
                     }
                     last = the_dir;
                     fout << vec[i] << endl;
                  }
               }
            }
            fout.close();
         }
      }
   }
   void usage() {
      cout << "cab cvf <file>.cab <dir>" << endl;
      cout << "- create cabinet file" << endl;
      cout << "cab xvf <file>.cab" << endl;
      cout << "- extract cabinet file" << endl;
   }
public:
   int run(const args_type & args) {
      int rc = 1;
      string file,dir;
      if(args.size() > 0) {
         if(args[0] == "xvf") {
            if(args.size() > 1) {
               file = args[1];
               dir = ".";
               if(args.size() == 3) {
                  dir = args[2];
               }
               rc = System("expand \""+quote(file)+"\" -F:* " + quote(dir));
            }
         }
         else if(args[0] == "cvf") {
            if(args.size() > 1) {
               file = args[1];
               if(args.size() > 2) {
                  dir = args[2];
                  rc = System("ls -R \"" + quote(dir) + "\" > cab-file-list.txt");
                  if(rc == 0) {
                     prep_file(dir);
                     rc = System("makecab /d \"CabinetName1=" + quote(file) + "\" /D DiskDirectoryTemplate=. /f cab2-file-list.txt");
                     unlink("cab-file-list.txt");
                     unlink("cab2-file-list.txt");
                  }
               }
            }
         }
         else {
            usage();
            rc = 0;
         }
      }
      else {
         usage();
         rc = 0;
      }
      return rc;
   }
};

int
main(int argc, char* argv[])
{
   cab CAB;
   args_type args;
   for(int i = 1; i < argc; i++) {
      args.push_back(argv[i]);
   }
   CAB.run(args);
   return 0;
}
