/* * Copyright (C) 2020 by SASANO Takayoshi JG1UAA * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "UserDB.h" #include "Log.h" #include #include #include CUserDB::CUserDB() : m_table(), m_mutex() { } CUserDB::~CUserDB() { } bool CUserDB::lookup(unsigned int id, class CUserDBentry *entry) { bool rv; m_mutex.lock(); try { if (entry != NULL) *entry = m_table.at(id); else (void)m_table.at(id); rv = true; } catch (...) { rv = false; } m_mutex.unlock(); return rv; } bool CUserDB::load(std::string const& filename) { LogInfo("Loading ID lookup table from %s", filename.c_str()); FILE* fp = ::fopen(filename.c_str(), "rt"); if (fp == NULL) { LogWarning("Cannot open ID lookup file - %s", filename.c_str()); return false; } m_mutex.lock(); // Remove the old entries; m_table.clear(); // set index for entries char buffer[256U]; if (::fgets(buffer, sizeof(buffer), fp) == NULL) { LogWarning("ID lookup file has no entry - %s", filename.c_str()); m_mutex.unlock(); ::fclose(fp); return false; } // no index - set default std::unordered_map index; if (!makeindex(buffer, index)) { ::strncpy(buffer, keyRADIO_ID "," keyCALLSIGN "," keyFIRST_NAME, sizeof(buffer)); makeindex(buffer, index); ::rewind(fp); } while (::fgets(buffer, sizeof(buffer), fp) != NULL) { if (buffer[0U] != '#') parse(buffer, index); } ::fclose(fp); size_t size = m_table.size(); m_mutex.unlock(); LogInfo("Loaded %u IDs to lookup table - %s", size, filename.c_str()); return size != 0U; } bool CUserDB::makeindex(char* buf, std::unordered_map& index) { int i; char *p1, *p2; // Remove the old index index.clear(); for (i = 0, p1 = tokenize(buf, &p2); p1 != NULL; i++, p1 = tokenize(p2, &p2)) { // create [column keyword] - [column number] table if (CUserDBentry::isValidKey(p1)) index[p1] = i; } try { (void)index.at(keyRADIO_ID); (void)index.at(keyCALLSIGN); return true; } catch (...) { return false; } } void CUserDB::parse(char* buf, std::unordered_map& index) { int i; char *p1, *p2; std::unordered_map ptr; unsigned int id; for (i = 0, p1 = tokenize(buf, &p2); p1 != NULL; i++, p1 = tokenize(p2, &p2)) { for (auto it = index.begin(); it != index.end(); it++) { // first: column keyword, second: column number if (it->second == i) { ptr[it->first] = p1; break; } } } try { (void)ptr.at(keyRADIO_ID); (void)ptr.at(keyCALLSIGN); } catch (...) { return; } id = (unsigned int)::atoi(ptr[keyRADIO_ID]); toupper_string(ptr[keyCALLSIGN]); for (auto it = ptr.begin(); it != ptr.end(); it++) { // no need to regist radio ID if (it->first == keyRADIO_ID) continue; m_table[id].set(it->first, it->second); } } void CUserDB::toupper_string(char* str) { while (*str != '\0') { *str = ::toupper(*str); str++; } } char* CUserDB::tokenize(char* str, char** next) { if (*str == '\0') return NULL; char* p = ::strpbrk(str, ",\t\r\n"); if (p == NULL) { *next = str + ::strlen(str); } else { *p = '\0'; *next = p + 1; } return str; }