| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508 | #include "utils.h"#include <algorithm> // transform#include <fstream>#include <sstream>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <string>#include <time.h>// http://c-faq.com/lib/randrange.htmlint randint(int N) { return rand() / (RAND_MAX / N + 1); }// http://c-faq.com/lib/randrange.html// numbers in the range [M, N] could be generated with something likeint randrange(int M, int N) {  return M + rand() / (RAND_MAX / (N - M + 1) + 1);}/** * random_activate() * * Is a weight (1-10), * tests if random number is < weight * 10. * * So random_activate(9) happens more frequently * then random_activate(8) or lower. * * This probably needs to be fixed. * We need a better randint(RANGE) code. */int random_activate(int w) {  int r = randint(100);  if (r <= w) {    return 1;  };  return 0;}/** * Display a repr of the given string. * * This converts most \n\r\v\f\t codes, * defaults to \xHH (hex value). */char *repr(const char *data) {  static char buffer[40960];  char *cp;  strcpy(buffer, data);  cp = buffer;  while (*cp != 0) {    char c = *cp;    if (c == ' ') {      cp++;      continue;    };    /* Ok, it's form-feed ('\f'), newline ('\n'), carriage return ('\r'),     * horizontal tab ('\t'), and vertical tab ('\v') */    if (strchr("\f\n\r\t\v\?", c) != NULL) {      memmove(cp + 1, cp, strlen(cp) + 1);      *cp = '\\';      cp++;      switch (c) {      case '\f':        *cp = 'f';        cp++;        break;      case '\n':        *cp = 'n';        cp++;        break;      case '\r':        *cp = 'r';        cp++;        break;      case '\t':        *cp = 't';        cp++;        break;      case '\v':        *cp = 'v';        cp++;        break;      default:        *cp = '?';        cp++;        break;      }      continue;    }    if (c == '\\') {      memmove(cp + 1, cp, strlen(cp) + 1);      *cp = '\\';      cp += 2;      continue;    }    if (c == '"') {      memmove(cp + 1, cp, strlen(cp) + 1);      *cp = '\\';      cp += 2;      continue;    }    if (strchr("[()]{}:;,.<>?!@#$%^&*", c) != NULL) {      cp++;      continue;    }    if (strchr("0123456789", c) != NULL) {      cp++;      continue;    }    if (strchr("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", c) !=        NULL) {      cp++;      continue;    }    // Ok, default to \xHH output.    memmove(cp + 3, cp, strlen(cp) + 1);    char buffer[10];    // int slen =    snprintf(buffer, sizeof(buffer), "\\x%02x", (int)c & 0xff);    /*    if (slen >= sizeof(buffer)) {      ZF_LOGE("snprintf %d > size %d", slen, (int)sizeof(buffer));    }    */    strncpy(cp, buffer, 4);    cp += 4;    continue;  }  return buffer;}/* * strnstr() * * buffer safe version that looks for a string. */const char *strnstr(const char *source, int len, const char *needle) {  int pos;  for (pos = 0; pos < len; pos++) {    if (source[pos] == needle[0]) {      if (strncmp(source + pos, needle, strlen(needle)) == 0) {        return source + pos;      }    }  }  return NULL;}/* * rstrnstr() Reverse string find in a string * * This obeys the len, and handles nulls in buffer. * find is a c-string (null terminated) */int rstrnstr(const char *buffer, int len, const char *find) {  int flen = strlen(find);  if (len < flen) {    // I can't find a string in a buffer smaller then it is!    return -1;  }  int pos = len - flen;  while (pos > 0) {    if (buffer[pos] == find[0]) {      // First chars match, check them all.      if (strncmp(buffer + pos, find, flen) == 0) {        return pos;      }    }    pos--;  }  return -1;}/* * string_insert() * Inserts a string into a given position. * This safely checks to make sure the buffer isn't overrun. * * buffer is a c null terminated string. */int string_insert(char *buffer, size_t max_length, size_t pos,                  const char *insert) {  /*  assert(max_length > pos);  assert(buffer != NULL);  assert(insert != NULL);  */  if (pos >= max_length)    return 0;  if (buffer == NULL)    return 0;  if (insert == NULL)    return 0;  if (strlen(insert) == 0)    return 0;  if (pos > strlen(buffer))    return 0;  if (strlen(buffer) + strlen(insert) >= max_length) {    /*    ZF_LOGD("string_insert() failed inserting [%s]", repr(insert));    */    return 0;  }  memmove(buffer + pos + strlen(insert), buffer + pos,          strlen(buffer + pos) + 1);  // cp + strlen(display), cp, strlen(cp) + 1);  strncpy(buffer + pos, insert, strlen(insert));  // (cp, display, strlen(display));  return 1; // success}void remove_all(std::string &str, char c) {str.erase(std::remove(str.begin(), str.end(), c), str.end());}/*Pascal String Copy.  Copy from pascal string, to C String.First char is pascal string length.  (Max 255). */void pcopy(char *pstring, char *str) {  int len = (int)*pstring;  strncpy(str, pstring + 1, len);  str[len] = 0;}/* * tail file, return new lines of text. * * Only handles lines < 256 chars. * Does not handle if the file is closed/unlinked/... * */std::string &find_new_text(std::ifstream &infile,                           std::streampos &last_position) {  static std::string line;  line.clear();  infile.seekg(0, std::ios::end);  std::streampos filesize = infile.tellg();  if (filesize == -1) {    // Ok, we've failed somehow.  Now what?    // cout << "SNAP!";    return line;  }  // check if the new file started  // we don't detect if the file has been unlinked/reset  if (filesize < last_position) {    // cout << "reset! " << filesize << endl;    last_position = 0;  }  while (last_position < filesize) {    // this loop -- seems broken.    // for (long n = last_position; n < filesize; n++) {    infile.seekg(last_position, std::ios::beg);    char test[256];    infile.getline(test, sizeof(test));    if (infile.eof()) {      // We got EOF instead of something.      // Seek back to our last, good, known position      // and exit (wait for the rest of the line)      infile.seekg(last_position, std::ios::beg);      return line;    }    std::streampos new_pos = infile.tellg();    if (new_pos == -1)      return line;    last_position = new_pos;    line.assign(test);    return line;  }  return line;}void string_toupper(std::string &str) {  std::transform(str.begin(), str.end(), str.begin(), ::toupper);}void string_trim(std::string &value) {  while (*value.begin() == ' ')    value.erase(value.begin());  while (*(value.end() - 1) == ' ')    value.erase(value.end() - 1);}std::map<std::string, std::string> read_configfile(std::string filename) {  std::ifstream file(filename);  std::string line;  std::map<std::string, std::string> config;  if (!file.is_open())    return config;  while (std::getline(file, line)) {    if ((line[0] == '#') || (line[0] == ';'))      continue;    if (line.empty())      continue;    // I'm not so sure this part is very good.    std::istringstream is_line(line);    std::string key;    if (std::getline(is_line, key, '=')) {      string_trim(key);      string_toupper(key);      std::string value;      if (std::getline(is_line, value)) {        string_trim(value);        config[key] = value;        /*                std::cout << "Key: [" << key << "] Value: [" << value << "]"                          << std::endl;        */      }    }  }  return config;}bool replace(std::string &str, const std::string &from, const std::string &to) {  size_t start_pos = str.find(from);  if (start_pos == std::string::npos)    return false;  str.replace(start_pos, from.length(), to);  return true;}IConv::IConv(const char *to, const char *from) : ic(iconv_open(to, from)) {}IConv::~IConv() { iconv_close(ic); }int IConv::convert(char *input, char *output, size_t outbufsize) {  size_t inbufsize = strlen(input);  // size_t orig_size = outbufsize;  // memset(output, 0, outbufsize);  // https://www.gnu.org/savannah-checkouts/gnu/libiconv/documentation/libiconv-1.15/iconv.3.html  int r = iconv(ic, &input, &inbufsize, &output, &outbufsize);  *output = 0;  return r;}static IConv converter("UTF-8", "CP437");static time_t last_time = 0;std::map<std::string, std::string> CONFIG = read_configfile("hharry.cfg");/* * harry_level: * *  0 - inactive *  1 - Week 1 (1-7) *  2 - Week 2 (8-14) *  3 - Week 3 (15-21) *  4 - Week 4 (22-31) */int harry_level(void) {  struct tm *tmp;  time_t now = time(NULL);  static int last = 0;  auto search = CONFIG.find("LEVEL");  if (search != CONFIG.end()) {    last = stoi(search->second);    if (last > 4) {      last = 4;    }    if (last < 0) {      last = 0;    }    return last;  }  if (last_time < now + 10) {    last_time = now;    // Do our every 10 second checks here    tmp = gmtime(&now);    if (tmp->tm_mon != 9)      return (last = 0);    if (tmp->tm_mday < 8)      return (last = 1);    if (tmp->tm_mday < 15)      return (last = 2);    if (tmp->tm_mday < 22)      return (last = 3);    return (last = 4);  }  return last;}/* * This is similar to repr, but -- * * It converts high ASCII to UTF8, so it will display correctly * in the logfiles! */const char *logrepr(const char *input) {  static char buffer[10240];  char *cp;  strcpy(buffer, input);  cp = buffer;  while (*cp != 0) {    unsigned char c = *cp;    if (c == ' ') {      cp++;      continue;    };    /* Ok, it's form-feed ('\f'), newline ('\n'), carriage return ('\r'),     * horizontal tab ('\t'), and vertical tab ('\v') */    if (strchr("\f\n\r\t\v", c) != NULL) {      memmove(cp + 1, cp, strlen(cp) + 1);      *cp = '\\';      cp++;      switch (c) {      case '\f':        *cp = 'f';        cp++;        break;      case '\n':        *cp = 'n';        cp++;        break;      case '\r':        *cp = 'r';        cp++;        break;      case '\t':        *cp = 't';        cp++;        break;      case '\v':        *cp = 'v';        cp++;        break;        /*      default:                *cp = '?';                cp++;                break; */      }      continue;    }    if (c == '\\') {      memmove(cp + 1, cp, strlen(cp) + 1);      *cp = '\\';      cp += 2;      continue;    }    if (c == '"') {      memmove(cp + 1, cp, strlen(cp) + 1);      *cp = '\\';      cp += 2;      continue;    }    if (strchr("[()]{}:;,.<>?!@#$%^&*", c) != NULL) {      cp++;      continue;    }    if (strchr("0123456789", c) != NULL) {      cp++;      continue;    }    if (strchr("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", c) !=        NULL) {      cp++;      continue;    }    if ((int)c < 0x20) {      // Ok, default to \xHH output.      memmove(cp + 3, cp, strlen(cp) + 1);      char buffer[10];      // int slen =      snprintf(buffer, sizeof(buffer), "\\x%02x", (int)c & 0xff);      strncpy(cp, buffer, 4);      cp += 4;      continue;    };    cp++;    continue;  }  static char fancybuffer[16384];  converter.convert(buffer, fancybuffer, sizeof(fancybuffer));  return fancybuffer;}
 |