/* Copyright 2013 Willem Vermin, SURFsara Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include #include #include #include #include "stopos.h" #include "wutils.h" #include "stopos_pool.h" #ifdef MAKE_GDBM #include "gdbm_pool.h" #endif #ifdef MAKE_FLAT #include "flatfile_pool.h" #endif #ifdef MAKE_FILES #include "files_pool.h" #endif #ifdef MAKE_MYSQL #include "mysql_pool.h" #endif void output(const std::string &return_message, const std::string &key, longuint committed, longuint count, longuint present, longuint present0, const std::string &return_value) { std::cout << "STOPOS:" << outsep << zstrtohex(return_message) << outsep << zstrtohex(key) << outsep << zstrtohex(NumberToString(committed)) << outsep << zstrtohex(NumberToString(count)) << outsep << zstrtohex(NumberToString(present)) << outsep << zstrtohex(NumberToString(present0)) << outsep << zstrtohex(return_value) << std::endl; } void output(const std::string &msg) { output(msg,"",0,0,0,0,""); } struct commandline { std::string header; std::string prot; std::string id; std::string pool; std::string command; std::string multi; std::string value; std::string full_dbname; std::string return_value; stopos_pool *handler; int create_full_dbname(void) { if (this->prot == "gdbm" || this->prot == "flat" || this->prot == "files") { std::string db_dir = DB_DIR; if (db_dir == "" ) db_dir = "/tmp"; db_dir += "/"; this->full_dbname = db_dir + zstrtohex(this->id) + "/" + zstrtohex(this->pool) + "_" + this->prot; } else if (this->prot == "mysql") { this->full_dbname = zstrtohex(this->id) + "_" + zstrtohex(this->pool); } else return 1; if (this->command != "pools") this->handler->set_db_name(this->full_dbname); return 0; } int create_handler() { #ifdef MAKE_GDBM if (this->prot == "gdbm") { this->handler = new gdbm_pool(); } #endif #ifdef MAKE_FLAT else if (this->prot == "flat") { this->handler = new flatfile_pool(); } #endif #ifdef MAKE_FILES else if (this->prot == "files") { this->handler = new files_pool(); } #endif #ifdef MAKE_MYSQL else if (this->prot == "mysql") { this->handler = new mysql_pool(); } #endif else { this->return_value = "ERROR: Unknown handler:" + this->prot; return 1; } return 0; } int init() { int rc; if (this->command != "pools") { rc = this->create_handler(); if (rc != 0) return rc; if (this->multi == "yes") this->handler->set_kvp(1); else this->handler->set_kvp(0); } rc = this->create_full_dbname(); return rc; } int create_db() { int rc = this->handler->create_db(); return rc; } int purge_db() { int rc = this->handler->purge_db(); return rc; } int add_line(std::string &key, std::string &r) { r = ""; int rc; rc = this->handler->open_db(); if (rc != 0) return rc; rc = this->handler->add_line(this->value,key); return rc; } int get_line(std::string &key, longuint &comm, std::string &r) { r = ""; int rc; rc = this->handler->open_db(); if (rc != 0) return rc; rc = this->handler->get_line(this->return_value, comm, key); return rc; } int dump_line(std::string &key, longuint &comm, std::string &r) { r = ""; int rc; rc = this->handler->open_db(); if (rc != 0) return rc; rc = this->handler->dump_line(this->return_value, comm, key); return rc; } int remove_line(std::string & rkey,std::string &key, std::string &r) { r = ""; int rc; rc = this->handler->open_db(); if (rc != 0) return rc; rkey = key; rc = this->handler->remove_line(key); return rc; } int get_status(longuint &count, longuint &present, longuint &present0, std::string &r) { r = ""; int rc; rc = this->handler->open_db(); if (rc != 0) return rc; rc = this->handler->get_counts(count, present, present0); return rc; } }; std::string sanitycheck(commandline &l) { if (l.header != "stopos") return "invalid header: '" + l.header + "'"; if (l.prot.find_first_of(' ') != l.prot.npos) return "ERROR: No valid protocol given"; if(l.id.find_first_of(' ') != l.id.npos) return "ERROR: No valid id given"; if(l.command != "pools") if(l.pool.find_first_of(' ') != l.pool.npos) { return "ERROR: No valid pool given"; } if(l.command.find_first_of(' ') != l.command.npos) { return "ERROR: No valid command given"; } return ""; } int parsecom(commandline &l,std::string &line) { std::vector v; split(v,line,httpsep); for (unsigned int i =0; i v; get_dir_list(v,dir); v.sort(); l.return_value = ""; for (std::list::iterator it=v.begin(); it != v.end(); ++it) { std::string f = *it; // // if suffix ( eg: _files ) is found // this could be a valid file name // size_t sufsize = l.prot.size()+1; if (sufsize > f.size()) continue; p = f.size() - sufsize; if (f.substr(p) != "_"+l.prot) continue; #if 0 p = f.rfind("_"+l.prot); if (p == f.npos) continue; #endif f = f.substr(0,p); // // strip directory part // p = f.find_last_of('/'); f = f.substr(p+1); l.return_value += zhextostr(f); l.return_value.push_back(' '); } if (l.return_value.size() > 0) l.return_value.erase(l.return_value.size()-1); } rc = 0; } } else rc = 1; if (rc == 0) return_message="OK"; else if (return_message == "") { switch (rc) { case stopos_pool::ERROR : return_message = "ERROR"; break; case stopos_pool::NOFILENAME : return_message = "ERROR: No file name given"; break; case stopos_pool::OPENERROR : return_message = "ERROR: Cannot find pool '" + l.pool + "'"; break; case stopos_pool::STOREERROR : return_message = "ERROR: Cannot write to pool '" + l.pool + "'"; break; case stopos_pool::FETCHERROR : return_message = "ERROR: Cannot read from pool '" + l.pool + "'"; break; case stopos_pool::NOTFOUND : return_message = "WARNING: Line not found"; break; case stopos_pool::NOTIMPLEMENTED : return_message = "ERROR: Feature not implemented"; break; case stopos_pool::REMOVEERROR : return_message = "ERROR: Cannot remove line"; break; case stopos_pool::LOCKERROR : return_message = "ERROR: Cannot get lock"; break; case stopos_pool::CLOSEERROR : return_message = "ERROR: Cannot close pool '" + l.pool + "'"; break; case stopos_pool::UNLOCKERROR : return_message = "ERROR: Cannot unlock pool '" + l.pool + "'"; break; case stopos_pool::DBNOTOPEN : return_message = "ERROR: Pool is not opened '" + l.pool + "'"; break; case stopos_pool::CREATEERROR : return_message = "ERROR: Cannot create pool '" + l.pool + "'"; break; case stopos_pool::PURGEERROR : return_message = "ERROR: Cannot purge pool '" + l.pool + "'"; break; case stopos_pool::RECORDTOOLONG : return_message = "ERROR: Record too long"; break; default : return_message = "ERROR"; break; } } output(return_message, key, committed, count, present, present0, l.return_value); return rc; } int main() { int rc; std::cout << "Content-Type: text/plain\n\n"; std::string line; line = envtostr("QUERY_STRING"); if (line.size() >0) if (line[0] == '/') line.erase(0,1); commandline l; parsecom(l,line); std::string msg = sanitycheck(l); if (msg != "") { output(msg); return 1; } rc = executecom(l); return rc; }