#define VERSION_NUMBER "0.04.01" #include #include #include #include #include #include #include #include #include #ifdef _WIN32 // something #include #include #else #include #endif void installRes(std::string id, std::string where); int createDir(std::string path); int install_MXP(std::string mxp); int remove_MXP(std::string mxp); std::string root_path = "./"; bool uninstall = false; std::string cur_mxp; static char *script_keywords[] = {"install", "makedir", "concat", "version", "package", "execute", "dependent", 0}; enum scriptKeys { INSTALL, MAKEDIR, CONCAT, VERSION, PACKAGE, EXECUTE, DEPENDENT, NULL_KEYWORD }; int compareKeys(const char *name) { for(unsigned int i = 0; script_keywords[i] != 0; i++) { if(strcmp(name, script_keywords[i]) == 0) return i; } return NULL_KEYWORD; } std::string getToken(mascToken *token, char *buf) { int result = 0; while(( result = mascLex(token, buf)) == MID_SKIP) { mascTokenReset(token); } return token->token; } int main(int argc, char **argv) { try { mx::mxArgs argx(argc, argv); std::string install_str; std::string rt; rt = argx.testForItem("--root"); if(rt != "") chdir(rt.c_str()); install_str = argx.testForItem("--install"); if(install_str != "") { install_MXP(install_str); return EXIT_SUCCESS; } std::string rmv; rmv = argx.testForItem("--remove"); if(rmv != "") { remove_MXP(rmv); return EXIT_SUCCESS; } std::cout << "MX Package Installer Version " << VERSION_NUMBER << "\n"; std::cout << "usage: mxp-i --install=package.mxp\n"; return EXIT_SUCCESS; } catch ( mx::mxException &e ) { e.printError(std::cerr); return EXIT_FAILURE; } catch (std::exception &e) { std::cout << e.what() << "\n"; return EXIT_FAILURE; } catch ( ... ) { std::cout << "Unknown exception ... \n"; return EXIT_FAILURE; } return 0; } int createDir(std::string path) { #ifdef _WIN32 if(CreateDirectory(path.c_str(), 0)) #else int d = 0; if((d = mkdir(path.c_str(), 0775)) == 0) #endif { return 1; } else return 0; } void installRes(mx::mxClampResourceFile *rez, std::string id, std::string where) { if(uninstall == true) { std::cout << "uninstalling ....: " << where << "\n"; remove(where.c_str()); return; } std::cout << "installing resource: " << id << " to " << where << "\n"; std::fstream file; file.open(where.c_str(), std::ios::out | std::ios::binary); if(file.is_open()) { void *buf; unsigned int len = 0; buf = rez->accessRawBytes(id, len); ((char*)buf)[len] = 0; if(buf) { file.write((char*)buf, len); free(buf); } file.close(); } else std::cout << " failure "; } void scriptInstall(mx::mxClampResourceFile *rez, char *buf, unsigned int len) { mascToken token; mascInit(&token); token.source_length = len; int result = 0; std::vector files; std::vector folders; while ( ( result = mascLex(&token, buf) ) != MID_NULL) { if(result != MID_SKIP) { if(result == MID_LETTER) { int action = compareKeys(token.token); if(action != NULL_KEYWORD) { switch(action) { case MAKEDIR: { while(( result = mascLex(&token, buf)) == MID_SKIP) { mascTokenReset(&token); } std::string path=""; path += token.token; int d; if(uninstall == true) { folders.push_back(path); break; } #ifdef _WIN32 if(CreateDirectory(path.c_str(), 0)) #else if((d = mkdir(path.c_str(), 0775)) == 0) #endif { std::cout << "created directory " << path << "\n"; } else std::cout << "directory creation failed\n"; } break; case DEPENDENT: { std::string mod_w, mod_l, mod_ppc; std::string install_path; std::string gt; bool path = false; gt = getToken(&token, buf); if(gt == "-x") { path = true; mod_w = getToken(&token, buf); } else mod_w = gt; mod_l = getToken(&token, buf); mod_ppc = getToken(&token,buf); install_path =getToken(&token,buf); #ifdef _WIN32 if(path == true) { install_path += "/"; install_path += mod_w; } installRes(rez, mod_w, install_path); #endif #ifdef LINUX if(path == true) { install_path += "/"; install_path += mod_l; } installRes(rez, mod_l, install_path); #endif #ifdef PPC if(path == true) { install_path += "/"; install_path += mod_ppc; } installRes(rez, mod_ppc, install_path); #endif } break; case INSTALL: { while(( result = mascLex(&token, buf)) == MID_SKIP) { mascTokenReset(&token); } std::string id; id = token.token; while(( result = mascLex(&token, buf)) == MID_SKIP) { mascTokenReset(&token); } std::string where; where = root_path; where += token.token; installRes(rez, id, where); } break; case VERSION: { while(( result = mascLex(&token, buf)) == MID_SKIP) { mascTokenReset(&token); } std::string id; id = token.token; std::fstream fout; fout.open("data/version.txt", std::ios::out); fout << id << "\n"; fout.close(); } break; case PACKAGE: { while(( result = mascLex(&token, buf)) == MID_SKIP) { mascTokenReset(&token); } std::string id; id = token.token; if(uninstall == true) { char data[256]; sprintf(data, "data/registry/%s", id.c_str()); folders.push_back(data); break; } std::cout << "package being setup....\n"; std::fstream fout; fout.open("data/reg.dat", std::ios::app); if(!fout.is_open()) { fout.open("data/reg.dat", std::ios::out); if(!fout.is_open()) { std::cout << "cannot access reg.dat\n"; } } char *bufz; unsigned int size; fout.seekg(0, std::ios::end); size = fout.tellg(); fout.seekg(0, std::ios::beg); bufz = new char [ size + 1 ]; fout.read((char*)bufz, size); bufz[size]=0; std::string buffer; buffer = bufz; delete [] bufz; char fullpath[256]; sprintf(fullpath,"data/registry/%s", id.c_str()); if(buffer.find(id) == -1) { std::cout << "installing configure data for " << id << "\n"; fout << id << "\n"; createDir("data/registry"); if(createDir(fullpath) == 1) { std::fstream fi; char fname[256]; sprintf(fname, "%s/install.rmv", fullpath); fi.open(fname, std::ios::out); fi << buf << "\n"; fi.close(); } } else { fout << "updating.. package " << id << "\n"; std::fstream fi; char fname[256]; sprintf(fname, "%s/install.rmv", fullpath); fi.open(fname, std::ios::out); fi << buf << "\n"; fi.close(); } fout.close(); std::cout << "successfully intergrated\n"; } break; case CONCAT: { createDir("data/menu"); while(( result = mascLex(&token, buf)) == MID_SKIP) { mascTokenReset(&token); } std::string id; id = token.token; while (( result = mascLex(&token, buf)) == MID_SKIP) mascTokenReset(&token); std::string where; where = "data/menu/"; where += id; std::cout << "configuring menu item " << id << "\n"; //((char*)dat)[len] = 0; if(uninstall == true) { remove(where.c_str()); std::cout << "Removed menu item @ " << where << "\n"; } else { std::fstream stream; void *dat = 0; unsigned int len; dat = (void*) rez->accessRawBytes(id, len); ((char*)dat)[len] = 0; stream.open(where.c_str(), std::ios::out | std::ios::binary); stream.write((char*)dat, len); stream.close(); free(dat); } } break; } } } } mascTokenReset(&token); } if(uninstall == true) { std::cout << "attempting to remove folders...\n"; for(unsigned int i = 0; i < folders.size(); i++) { if( rmdir(folders[i].c_str()) == 0 ) { std::cout << "removed directory: " << folders[i] << "\n"; } } char data[256]; sprintf(data, "data/registry/%s/install.rmv", cur_mxp.c_str()); remove(data); sprintf(data, "data/registry/%s"); rmdir(data); } std::cout << "Complete\n"; } int install_MXP(std::string mxp) { mx::mxClampResourceFile rez(mxp); char *buf = 0; unsigned int len = 0; buf =(char*) rez.accessRawBytes("install.cfg", len); buf[len] = 0; if(buf == 0) throw mx::mxException( " error not mxp archive format "); scriptInstall(&rez, buf, len); free (buf); return 0; } int remove_MXP(std::string mxp) { std::fstream file; std::string path; path += "data/registry/"; path += mxp; path += "/install.rmv"; file.open(path.c_str(), std::ios::in | std::ios::binary); if(!file.is_open()) { std::cout << "package: " << mxp << " not installed\n"; exit(57); } char *buffer = 0; file.seekg(0,std::ios::end); size_t s = file.tellg(); buffer = new char [ s + 1 ]; file.seekg(0, std::ios::beg); file.read((char*)buffer, s); buffer [s] = 0; file.close(); uninstall = true; cur_mxp = mxp; scriptInstall(0, buffer, s); delete [] buffer; return 0; }