00001 // ----------------------------------------------------------------------^ 00002 // Copyright (C) 2004, 2005, 2006, 2007, 2008 Giorgio Calderone 00003 // (mailto: <gcalderone@ifc.inaf.it>) 00004 // 00005 // This file is part of MCS. 00006 // 00007 // MCS is free software; you can redistribute it and/or modify 00008 // it under the terms of the GNU General Public License as published by 00009 // the Free Software Foundation; either version 2 of the License, or 00010 // (at your option) any later version. 00011 // 00012 // MCS is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU General Public License 00018 // along with MCS; if not, write to the Free Software 00019 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00020 // 00021 // ----------------------------------------------------------------------$ 00022 #include "mcs.hh" 00023 using namespace mcs; 00024 00025 00026 int mcs::extractCode(const char* msg) 00027 { 00028 int ret; 00029 ret = 0; 00030 ret += (msg[1] - '0') * 100; 00031 ret += (msg[2] - '0') * 10 ; 00032 ret += (msg[3] - '0') ; 00033 return ret; 00034 } 00035 00036 00037 00038 00039 bool mcs::File_Dir_Exist(string fn, unsigned int& size) 00040 { 00041 DIR *dp; 00042 ifstream f; 00043 size = 0; 00044 00045 if (fn.empty()) return false; 00046 dp = opendir(fn.csz); 00047 if (dp) { 00048 closedir(dp); 00049 return true; 00050 } 00051 else { 00052 f.open(fn.csz); 00053 if (f.is_open()) { 00054 f.seekg(0, ios::end); // Seek the end of file (to get the size) 00055 size = f.tellg(); // Size of file 00056 f.seekg(0, ios::beg); // Seek the start of file 00057 f.close(); 00058 return true; 00059 } 00060 else 00061 return false; 00062 } 00063 } 00064 00065 00066 string mcs::Pwd() 00067 { 00068 char* p; 00069 string s; 00070 p=getcwd(NULL, 0); 00071 s=p; 00072 free(p); 00073 return s; 00074 } 00075 00076 00077 string mcs::itos(int i) 00078 { 00079 char buf[20]; 00080 sprintf(buf, "%d", i); 00081 return string(buf); 00082 } 00083 00084 00085 int mcs::stoi(string s) 00086 { 00087 int i; 00088 if (sscanf(s.c_str(), "%d", &i) == 1) 00089 return i; 00090 else 00091 throw MCS_ERROR(MSG_CONVERSION_STRING_INT); 00092 } 00093 00094 00095 int mcs::stoi(string s, int errval) 00096 { 00097 int i; 00098 if (sscanf(s.c_str(), "%d", &i) == 1) 00099 return i; 00100 else 00101 return errval; 00102 } 00103 00104 00105 string mcs::dtos(double f) 00106 { 00107 char buf[20]; 00108 sprintf(buf, "%f", f); 00109 return string(buf); 00110 } 00111 00112 00113 string mcs::btos(bool b) 00114 { 00115 if (b) 00116 return string("true"); 00117 else 00118 return string("false"); 00119 } 00120 00121 00122 string mcs::vtos(vector<string> vec) 00123 { 00124 unsigned int i; 00125 string buf = ""; 00126 string nl = "\n"; 00127 00128 for (i=0; i<vec.size(); i++) 00129 buf += vec[i] + nl; 00130 00131 return buf; 00132 } 00133 00134 00135 string mcs::subst(string s, string what, string with, int op) 00136 { 00137 string s2 = "(" + what + string(")"); 00138 string templ = s2; 00139 00140 if (op & MCS_SUBST_LEADING) 00141 templ = "^" + s2; 00142 00143 if (op & MCS_SUBST_TRAILING) { 00144 if (op & MCS_SUBST_LEADING) 00145 templ += "|" + s2; 00146 templ += "$"; 00147 } 00148 pcrecpp::RE re(templ, 00149 pcrecpp::RE_Options().set_dollar_endonly(true)); 00150 00151 if (op & MCS_SUBST_QUOTE_WITH) { 00152 pcrecpp::RE re("\\\\"); 00153 re.GlobalReplace("\\\\\\\\", &with); 00154 } 00155 re.GlobalReplace(with, &s); 00156 return s; 00157 } 00158 00159 00160 string mcs::trim(string s) 00161 { 00162 return subst(s, " +", "", MCS_SUBST_LEADING | MCS_SUBST_TRAILING); 00163 } 00164 00165 00166 string mcs::chomp(string s) 00167 { 00168 return subst(s, "\n+", "", MCS_SUBST_TRAILING); 00169 } 00170 00171 00172 string mcs::remTabs(string s) 00173 { 00174 return subst(s, "\t", ""); 00175 } 00176 00177 00178 string mcs::remLeading(string& s, const char* p) 00179 { 00180 s = subst(s, p, "", MCS_SUBST_LEADING); 00181 return s; 00182 } 00183 00184 00185 string mcs::remTrailing(string& s, const char* p) 00186 { 00187 s = subst(s, p, "", MCS_SUBST_TRAILING); 00188 return s; 00189 } 00190 00191 00192 std::vector<std::string> mcs::split(string s, string sep) 00193 { 00194 vector<string> v; 00195 00196 //First characters must not be equal top sep 00197 pcrecpp::RE pre("^\\Q" + sep + "\\E+"); 00198 pre.GlobalReplace("", &s); 00199 00200 pcrecpp::StringPiece input(s); 00201 pcrecpp::RE re("([^\\Q" + sep + "\\E]+)\\Q" + sep + "\\E*"); 00202 //pcrecpp::RE re("(\\S+) *"); 00203 00204 while (re.Consume(&input, &s)) 00205 v.push_back(s); 00206 00207 return v; 00208 } 00209 00210 00211 string mcs::hexDump(const void* pvoid, unsigned int size) 00212 { 00213 const char* buf = (const char*) pvoid; 00214 string s = ""; 00215 unsigned int i, j, count; 00216 char lbuf[40]; 00217 00218 i = 0; 00219 while (i < size) { 00220 count = size - i; 00221 if (count > 8) 00222 count = 8; 00223 00224 sprintf(lbuf, "%06d ", i); 00225 s += lbuf; 00226 00227 for (j=0; j<count; j++) { 00228 sprintf(lbuf, "%02X", buf[i+j]); 00229 s += lbuf; 00230 } 00231 00232 s += " "; 00233 00234 for (j=0; j<count; j++) { 00235 if (isprint(buf[i+j])) 00236 sprintf(lbuf, "%c", buf[i+j]); 00237 else 00238 sprintf(lbuf, "."); 00239 00240 s += lbuf; 00241 } 00242 00243 s += "\n"; 00244 i += count; 00245 } 00246 return s; 00247 } 00248 00249 00250 mode_t mcs::read_umask() 00251 { 00252 mode_t mask = umask (0); 00253 umask(mask); 00254 return mask; 00255 } 00256 00257 00258 00259 bool mcs::mkDir(string path, mode_t perm, enum ThrowExceptions throwexc) 00260 { 00261 if (perm == MCS_MKDIR_UMASK) 00262 perm = (S_IRWXU | S_IRWXG | S_IRWXO) & ~read_umask(); 00263 00264 if (mkdir(path.csz, perm)) 00265 if (throwexc) 00266 throw MCS_ERROR(MSG_CANT_MKDIR, path.csz); 00267 else 00268 return false; 00269 else 00270 return true; 00271 } 00272 00273 00274 bool mcs::rmDir(string path, enum ThrowExceptions throwexc) 00275 { 00276 string s; 00277 //TODO: custom "rmdir" 00278 s = "rm -rf " + path; 00279 00280 if (system(s.csz)) 00281 if (throwexc) 00282 throw MCS_ERROR(MSG_CANT_RMDIR, path.csz); 00283 else 00284 return false; 00285 else 00286 return true; 00287 } 00288 00289 00290 void mcs::ls2Record(string fn, Record& v) 00291 { 00292 DIR *dp; 00293 struct dirent *ep; 00294 string s, r; 00295 ifstream f; 00296 00297 if (fn.empty()) return; 00298 00299 dp = opendir (fn.c_str()); 00300 if (dp) { 00301 while ((ep = readdir (dp))) { 00302 r=ep->d_name; 00303 if ( r != "." && r != ".." ) 00304 ls2Record(fn + string("/") + r, v); 00305 } 00306 closedir (dp); 00307 } 00308 else { 00309 f.open(fn.c_str()); 00310 if (f.is_open()) { 00311 Data d(NULL, STRING, "FILE", fn.length()); 00312 d = fn; 00313 v.addField(&d); 00314 f.close(); 00315 } 00316 } 00317 } 00318 00319 00320 00321 00322 //This routine is to be used inside this file, not by users 00323 static char* appendFileNameToPath(char* OLDNAME, char* NEWNAME) 00324 { 00325 char* buf; 00326 char* p; 00327 00328 p = strrchr(OLDNAME, '/'); 00329 if (p == NULL) 00330 p = OLDNAME; 00331 else { 00332 p++; 00333 } 00334 00335 //Plus two: one to eventually add a slash, one for NULL 00336 buf = (char*) malloc(strlen(NEWNAME) + strlen(p) + 2); 00337 00338 strcpy(buf, NEWNAME); 00339 00340 if (buf[strlen(buf) - 1] != '/') { //If last character is not a slash 00341 buf[strlen(buf) + 1] = 0; 00342 buf[strlen(buf)] = '/'; 00343 } 00344 00345 strcpy(buf + strlen(buf), p); 00346 return buf; 00347 } 00348 00349 00350 00351 00352 #define BUFSIZE 16384 00353 int mcs::copy(char* OLDNAME, char* NEWNAME) 00354 { 00355 FILE *inf, *outf; 00356 int nread; 00357 char buf[BUFSIZE]; 00358 00359 if ((outf = fopen(NEWNAME, "wb")) == NULL) { 00360 if (errno == EISDIR) { 00361 char* b = appendFileNameToPath(OLDNAME, NEWNAME); 00362 int ret = copy(OLDNAME, b); 00363 free(b); 00364 return ret; 00365 } 00366 else { 00367 fprintf(stderr, "Error opening file %s: %s\n", NEWNAME, 00368 strerror(errno)); 00369 return -1; 00370 } 00371 } 00372 else { 00373 if ((inf = fopen(OLDNAME, "rb")) == NULL) { 00374 fclose(outf); 00375 fprintf(stderr, "Error opening file %s: %s\n", OLDNAME, 00376 strerror(errno)); 00377 return -1; 00378 } 00379 00380 00381 while (! feof(inf)) { 00382 nread = fread(buf, sizeof(char), BUFSIZE, inf); 00383 fwrite(buf, sizeof(char), nread, outf); 00384 } 00385 00386 fclose(inf); 00387 fclose(outf); 00388 00389 //Success 00390 return 0; 00391 } 00392 } 00393 00394 00395 int mcs::move(char* OLDNAME, char* NEWNAME) 00396 { 00397 char* buf; 00398 int ret; 00399 00400 ret = rename(OLDNAME, NEWNAME); 00401 00402 if (ret == -1) //An error occurred 00403 switch(errno) { 00404 00405 case EISDIR: //NEWNAME is a directory but the OLDNAME isn't. 00406 //So append the filename to the NEWNAME directory and retry 00407 buf = appendFileNameToPath(OLDNAME, NEWNAME); 00408 ret = move(OLDNAME, buf); 00409 free(buf); 00410 return ret; 00411 00412 00413 case EBUSY: //This error can happen if NEWNAME is one of: ".", ".." 00414 if (NEWNAME[strlen(NEWNAME) - 1] != '/') { //That's a directory 00415 buf = appendFileNameToPath(OLDNAME, NEWNAME); 00416 ret = move(OLDNAME, buf); 00417 free(buf); 00418 return ret; 00419 } 00420 00421 00422 case EXDEV: //Different filesystems, must copy, then delete 00423 ret = copy(OLDNAME, NEWNAME); 00424 if (ret == 0) { 00425 if (unlink(OLDNAME) == -1) { 00426 fprintf(stderr, "Error deleting file %s: %s\n", OLDNAME, 00427 strerror(errno)); 00428 return -1; 00429 } 00430 } 00431 return ret; 00432 00433 00434 00435 default: 00436 fprintf(stderr, "Error renaming %s ==> %s: %s\n", OLDNAME, NEWNAME, 00437 strerror(errno)); 00438 return -1; 00439 } 00440 00441 00442 //Success 00443 return 0; 00444 } 00445 00446 00447 00448 00449 00450 const char* mcs::B64_Codec::cb64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 00451 const char* mcs::B64_Codec::cd64="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq"; 00452 00453 00454 mcs::B64_Codec::B64_Codec() 00455 { 00456 bufAllocated = NULL; 00457 precDataCount = 0; 00458 blocksout = 0; 00459 } 00460 00461 mcs::B64_Codec::~B64_Codec() 00462 { 00463 freeBuffer(); 00464 } 00465 00466 00467 void mcs::B64_Codec::requireSpace(unsigned int Length) 00468 { 00469 if (Length < 0) 00470 ; //ERROR 00471 00472 if ((! bufAllocated) || 00473 (bufsize < Length)) { 00474 bufsize = Length; 00475 bufAllocated = (char*) realloc(bufAllocated, bufsize); 00476 memset(bufAllocated, 0, bufsize); 00477 } 00478 this->buf_out = bufAllocated; 00479 } 00480 00481 void mcs::B64_Codec::freeBuffer() 00482 { 00483 if (bufAllocated) 00484 free(bufAllocated); 00485 00486 bufAllocated = NULL; 00487 bufsize = 0; 00488 } 00489 00490 00491 bool mcs::B64_Codec::eob() 00492 { 00493 if (precDataCount) 00494 return false; 00495 else 00496 return ((bool) (pin >= EOIB)); 00497 } 00498 00499 unsigned char mcs::B64_Codec::readData() 00500 { 00501 if (precDataCount) { 00502 unsigned char ret = precData[0]; 00503 precData[0] = precData[1]; 00504 precData[1] = precData[2]; 00505 precData[2] = precData[3]; 00506 precDataCount--; 00507 return ret; 00508 } 00509 else 00510 return *pin++; 00511 } 00512 00513 void mcs::B64_Codec::writeData(unsigned char d) 00514 { *pout++ = d; } 00515 00516 char* mcs::B64_Codec::buffer() 00517 { return buf_out; } 00518 00519 unsigned int mcs::B64_Codec::bufUsed() 00520 { return pout - buf_out; } 00521 00522 00523 unsigned int mcs::B64_Codec::encode(char* buf_in, int Length, char* par_buf_out, 00524 unsigned int linesize) 00525 { 00526 unsigned int rescue = 0; 00527 unsigned char in[3], out[4]; 00528 int i, len = 0; 00529 00530 int origLength = Length; //Save "Length" because we are going to 00531 //change it. 00532 00533 //Number of bytes being read (those from precedent call: 00534 //precDataCount, plus actual buffer: Length) must be a multiple of 3 00535 //bytes. 00536 if (Length) { 00537 rescue = (precDataCount + Length) % 3; //"rescue" bytes need to be 00538 //saved for a later call. 00539 Length -= rescue; 00540 } 00541 00542 //Setup input buffer 00543 EOIB = buf_in + Length; 00544 pin = buf_in; 00545 00546 //Setup output buffer 00547 if (par_buf_out) { 00548 freeBuffer(); 00549 buf_out = par_buf_out; 00550 } 00551 else { 00552 requireSpace(origLength * 2); 00553 buf_out = bufAllocated; 00554 } 00555 pout = buf_out; 00556 00557 00558 //Set linesize 00559 if (linesize < MCS_B64_MIN_LINE) 00560 linesize = MCS_B64_MIN_LINE; 00561 this->linesize = linesize; 00562 00563 00564 //Encode 00565 while (! eob()) { 00566 len = 0; 00567 for(i=0; i<3; i++) { 00568 if (! eob()) { 00569 in[i] = (unsigned char) readData(); 00570 len++; 00571 } 00572 else 00573 in[i] = 0; 00574 } 00575 if (len) { 00576 encodeblock(in, out, len); 00577 for(i=0; i<4; i++) { 00578 writeData(out[i]); 00579 } 00580 blocksout++; 00581 } 00582 if (blocksout >= (linesize/4)) { 00583 writeData('\r'); 00584 writeData('\n'); 00585 blocksout = 0; 00586 } 00587 } 00588 00589 00590 if (Length) { //Save bytes from input buffer for a later call 00591 for (unsigned int i=0; i<rescue; i++) 00592 precData[i] = readData(); 00593 00594 precDataCount = rescue; 00595 } 00596 else { //Or if we are at end of file simply write a newline 00597 writeData('\r'); 00598 writeData('\n'); 00599 00600 precDataCount = 0; //Setup for new encoding 00601 blocksout = 0; 00602 } 00603 00604 return pout - buf_out; 00605 } 00606 00607 00608 00609 unsigned int mcs::B64_Codec::decode(char* buf_in, int Length, char* par_buf_out) 00610 { 00611 unsigned char in[4], out[3], v, d; 00612 int i, len; 00613 00614 //Setup input buffer 00615 EOIB = buf_in + Length; 00616 pin = buf_in; 00617 00618 //Setup output buffer 00619 if (par_buf_out) { 00620 freeBuffer(); 00621 buf_out = par_buf_out; 00622 } 00623 else { 00624 requireSpace(Length); 00625 buf_out = bufAllocated; 00626 } 00627 pout = buf_out; 00628 00629 00630 //Decode data 00631 len = 0; 00632 while (! eob()) { 00633 d = v = readData(); 00634 00635 //Check if the character is allowed 00636 v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]); 00637 if ((v != 0) && 00638 (v != '$') ) { 00639 in[len] = v - 62; 00640 00641 if (precDataCount == 0) 00642 precData[len] = d; 00643 00644 len++; 00645 } 00646 00647 //If we have a complete 4 byte block 00648 if (len == 4) { 00649 decodeblock(in, out); 00650 for(i=0; i<len-1; i++) 00651 writeData(out[i]); 00652 00653 len = 0; 00654 } 00655 } 00656 00657 if (len > 0) { //If some byte hasn't been decoded yet 00658 precDataCount = len; //...save it for a later call 00659 00660 if (Length == 0) { //Or if we are at the end of file 00661 decodeblock(in, out); //..decode it! 00662 for(i=0; i<len-1; i++) 00663 writeData(out[i]); 00664 00665 precDataCount = 0; //Setup for new encoding 00666 } 00667 } 00668 00669 return pout - buf_out; 00670 } 00671 00672 void mcs::B64_Codec::encodeblock( unsigned char in[3], unsigned char out[4], int len ) 00673 { 00674 out[0] = cb64[ in[0] >> 2 ]; 00675 out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ]; 00676 out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '='); 00677 out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '='); 00678 } 00679 00680 void mcs::B64_Codec::decodeblock( unsigned char in[4], unsigned char out[3] ) 00681 { 00682 out[ 0 ] = (unsigned char ) (in[0] << 2 | in[1] >> 4); 00683 out[ 1 ] = (unsigned char ) (in[1] << 4 | in[2] >> 2); 00684 out[ 2 ] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]); 00685 } 00686 00687 00688 00689 00690 //returns 0 if timeout, 1 if ready, -1 if error 00691 int mcs::Select(int fd, unsigned int sec_timeout, unsigned int usec_timeout, int op) 00692 { 00693 fd_set set; 00694 struct timeval timeout; 00695 int ret; 00696 00697 FD_ZERO (&set); 00698 FD_SET (fd, &set); 00699 timeout.tv_sec = sec_timeout; 00700 timeout.tv_usec = usec_timeout; 00701 00702 if (op == MCS_SELECT_READ) 00703 ret = select(FD_SETSIZE, &set, NULL, NULL, &timeout); 00704 else 00705 ret = select(FD_SETSIZE, NULL, &set, NULL, &timeout); 00706 00707 return ret; 00708 } 00709 00710 00711 00712 //returns 0 if timeout, number of fd ready, -1 if error 00713 int mcs::Select(int fd[], int nfd, unsigned int sec_timeout, unsigned int usec_timeout, int op) 00714 { 00715 fd_set set; 00716 struct timeval timeout; 00717 int i, ret; 00718 00719 FD_ZERO (&set); 00720 for (i=0; i<nfd; i++) { 00721 FD_SET (fd[i], &set); 00722 fd[i] = 0; 00723 } 00724 00725 timeout.tv_sec = sec_timeout; 00726 timeout.tv_usec = usec_timeout; 00727 00728 if (op == MCS_SELECT_READ) 00729 ret = select(FD_SETSIZE, &set, NULL, NULL, &timeout); 00730 else 00731 ret = select(FD_SETSIZE, NULL, &set, NULL, &timeout); 00732 00733 for (i=0; i<nfd; i++) 00734 fd[i] = FD_ISSET(i, &set); 00735 00736 return ret; 00737 } 00738 00739 00740
![]() |
MCS (My Customizable Server) ver. 0.3.3-alpha3
|