123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532 |
- #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.html
- int 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 like
- int 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());
- }
- int unicode_len(char choad) {
- /*
- return length of unicode sequence, or 0 if not a unicode.
- */
- // https://en.wikipedia.org/wiki/UTF-8
-
- // 110xxxxx
- if ((choad & 0xe0) == 0xc0) {
- // CHOAD!
- return 2;
- }
- // 1110xxxx
- if ((choad & 0xf0) == 0xe0) {
- return 3;
- }
- // 11110xxx
- if ((choad & 0xf8) == 0xf0) {
- return 4;
- }
- return 0;
- }
- /*
- 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;
- }
|