From b3a4f05d9f7f36d4822bbcfce6785f98bc0bf4fa Mon Sep 17 00:00:00 2001 From: katze Date: Wed, 11 Nov 2020 02:46:45 +0100 Subject: [PATCH] Upload files to 'tool/PGListUtil/src/common' --- tool/PGListUtil/src/common/CErrorList.cpp | 171 +++++++++++ tool/PGListUtil/src/common/CErrorList.h | 43 +++ tool/PGListUtil/src/common/CFilter.cpp | 125 ++++++++ tool/PGListUtil/src/common/CFilter.h | 34 +++ tool/PGListUtil/src/common/CIpList.cpp | 355 ++++++++++++++++++++++ 5 files changed, 728 insertions(+) create mode 100644 tool/PGListUtil/src/common/CErrorList.cpp create mode 100644 tool/PGListUtil/src/common/CErrorList.h create mode 100644 tool/PGListUtil/src/common/CFilter.cpp create mode 100644 tool/PGListUtil/src/common/CFilter.h create mode 100644 tool/PGListUtil/src/common/CIpList.cpp diff --git a/tool/PGListUtil/src/common/CErrorList.cpp b/tool/PGListUtil/src/common/CErrorList.cpp new file mode 100644 index 00000000..4dce97bc --- /dev/null +++ b/tool/PGListUtil/src/common/CErrorList.cpp @@ -0,0 +1,171 @@ +#include +#include +#include "CErrorList.h" + +namespace pglu { +namespace error { + +CErrorList::CErrorList() : + m_pool(sizeof(CError)), + m_errFoot(&m_errHead), + m_errNext(&m_errHead), + m_count(0) +{ + m_errHead.line = 0; + m_errHead.kind = SYNTAX; + m_errHead.next = NULL; +} + +CErrorList::~CErrorList() { + Clear(); +} + +void CErrorList::Clear() { + m_pool.purge_memory(); + m_errHead.next = NULL; + m_errFoot = &m_errHead; + m_errNext = &m_errHead; + m_count = 0; +} + +bool CErrorList::LoadListFile(const char *path) { + char buf[PGLU_LENGTH_FILELINE]; + uint ip_begin1, ip_begin2, ip_begin3, ip_begin4; + uint ip_end1, ip_end2, ip_end3, ip_end4; + FILE *fp; + CError *err = m_errFoot; + + using namespace boost::xpressive; + + static cmatch match; + static mark_tag tagIp1(1), tagIp2(2), tagIp3(3), tagIp4(4), tagIp5(5), tagIp6(6), tagIp7(7), tagIp8(8); + static mark_tag tagSep(9), tagMask(10); + + static cregex reSyntax = + as_xpr(':') >> *_s >> + (tagIp1 = repeat<1, 3>(_d)) >> as_xpr('.') >> + (tagIp2 = repeat<1, 3>(_d)) >> as_xpr('.') >> + (tagIp3 = repeat<1, 3>(_d)) >> as_xpr('.') >> + (tagIp4 = repeat<1, 3>(_d)) >> + *_s >> as_xpr('-') >> *_s >> + (tagIp5 = repeat<1, 3>(_d)) >> as_xpr('.') >> + (tagIp6 = repeat<1, 3>(_d)) >> as_xpr('.') >> + (tagIp7 = repeat<1, 3>(_d)) >> as_xpr('.') >> + (tagIp8 = repeat<1, 3>(_d)) >> + *_s >> (_ln | eos); + + static cregex reSyntaxRestorable = + (tagIp1 = repeat<1, 3>(_d)) >> (set = '.', ',') >> + (tagIp2 = repeat<1, 3>(_d)) >> (set = '.', ',') >> + (tagIp3 = repeat<1, 3>(_d)) >> (set = '.', ',') >> + (tagIp4 = repeat<1, 3>(_d)) >> *_s >> ( + (tagSep = +as_xpr('-')) >> *_s >> + (tagIp5 = repeat<1, 3>(_d)) >> (set = '.', ',') >> + (tagIp6 = repeat<1, 3>(_d)) >> (set = '.', ',') >> + (tagIp7 = repeat<1, 3>(_d)) >> (set = '.', ',') >> + (tagIp8 = repeat<1, 3>(_d)) + | + (tagSep = +(set = '/', '\\')) >> *_s >> + (tagMask = repeat<1, 2>(_d)) + ) >> *_s >> (_ln | eos); + +#define reIpError repeat<3>(+_d >> *_s >> (set = '.', ',') >> *_s) >> +_d + + static cregex reSyntaxError = + reIpError >> *_s >> ( + *as_xpr('-') >> *_s >> reIpError | + +(set = '/', '\\') >> *_s >> +_d + ); + + fp = fopen(path, "r"); + if(fp == NULL) + return false; + + for(int line = 1; fgets(buf, PGLU_LENGTH_FILELINE, fp); ++line) { + + if(regex_search(buf, match, reSyntax)) { + if(!( + (ip_begin1 = ParseDigit3(match[1].first, match[1].second)) < 256 && + (ip_begin2 = ParseDigit3(match[2].first, match[2].second)) < 256 && + (ip_begin3 = ParseDigit3(match[3].first, match[3].second)) < 256 && + (ip_begin4 = ParseDigit3(match[4].first, match[4].second)) < 256 && + (ip_end1 = ParseDigit3(match[5].first, match[5].second)) < 256 && + (ip_end2 = ParseDigit3(match[6].first, match[6].second)) < 256 && + (ip_end3 = ParseDigit3(match[7].first, match[7].second)) < 256 && + (ip_end4 = ParseDigit3(match[8].first, match[8].second)) < 256 && + (uint)((ip_begin1 << 24) | (ip_begin2 << 16) | (ip_begin3 << 8) | ip_begin4) <= + (uint)((ip_end1 << 24) | (ip_end2 << 16) | (ip_end3 << 8) | ip_end4) + )) { + ++m_count; + err->next = (CError*)m_pool.malloc(); + err = err->next; + err->line = line; + err->kind = IP; + } + + } else if(regex_search(buf, match, reSyntaxRestorable)) { + ++m_count; + err->next = (CError*)m_pool.malloc(); + err = err->next; + err->line = line; + if(*(match[9].first) == '-') { + if( + (ip_begin1 = ParseDigit3(match[1].first, match[1].second)) < 256 && + (ip_begin2 = ParseDigit3(match[2].first, match[2].second)) < 256 && + (ip_begin3 = ParseDigit3(match[3].first, match[3].second)) < 256 && + (ip_begin4 = ParseDigit3(match[4].first, match[4].second)) < 256 && + (ip_end1 = ParseDigit3(match[5].first, match[5].second)) < 256 && + (ip_end2 = ParseDigit3(match[6].first, match[6].second)) < 256 && + (ip_end3 = ParseDigit3(match[7].first, match[7].second)) < 256 && + (ip_end4 = ParseDigit3(match[8].first, match[8].second)) < 256 && + (uint)((ip_begin1 << 24) | (ip_begin2 << 16) | (ip_begin3 << 8) | ip_begin4) <= + (uint)((ip_end1 << 24) | (ip_end2 << 16) | (ip_end3 << 8) | ip_end4) + ) { + err->kind = SYNTAX_RESTORABLE; + } else { + err->kind = SYNTAX; + } + } else { + uint mask = ParseDigit3(match[10].first, match[10].second); + if( + ParseDigit3(match[1].first, match[1].second) < 256 && + ParseDigit3(match[2].first, match[2].second) < 256 && + ParseDigit3(match[3].first, match[3].second) < 256 && + ParseDigit3(match[4].first, match[4].second) < 256 && + mask < 33 + ) { + err->kind = SYNTAX_RESTORABLE; + } else { + err->kind = SYNTAX; + } + } + } else if(regex_search(buf, reSyntaxError)) { + ++m_count; + err->next = (CError*)m_pool.malloc(); + err = err->next; + err->line = line; + err->kind = SYNTAX; + } +#ifdef __MINGW32__ + ZeroString(buf); +#endif + } + + fclose(fp); + err->next = NULL; + m_errFoot = err; + return true; +} + +int CErrorList::Count() { + return m_count; +} + +CError * CErrorList::GetNext() { + if(m_errNext) + m_errNext = m_errNext->next; + return m_errNext; +} + +} // namespace error +} // namespace pglu diff --git a/tool/PGListUtil/src/common/CErrorList.h b/tool/PGListUtil/src/common/CErrorList.h new file mode 100644 index 00000000..5583bb8d --- /dev/null +++ b/tool/PGListUtil/src/common/CErrorList.h @@ -0,0 +1,43 @@ +#ifndef CERRLIST_H +#define CERRLIST_H + +#include +#include "common.h" + +namespace pglu { +namespace error { + +typedef enum _EErrKind { + SYNTAX, + IP, + SYNTAX_RESTORABLE +} EErrKind; + +typedef struct _CError { + int line; + EErrKind kind; + _CError * next; +} CError; + +class CErrorList { +private: + boost::pool<> m_pool; + CError m_errHead; + CError * m_errFoot; + CError * m_errNext; + int m_count; + +public: + CErrorList(); + ~CErrorList(); + + void Clear(); + bool LoadListFile(const char *path); + int Count(); + CError * GetNext(); +}; + +} // namespace error +} // namespace pglu + +#endif // CERRLIST_H diff --git a/tool/PGListUtil/src/common/CFilter.cpp b/tool/PGListUtil/src/common/CFilter.cpp new file mode 100644 index 00000000..a6235547 --- /dev/null +++ b/tool/PGListUtil/src/common/CFilter.cpp @@ -0,0 +1,125 @@ +#include +#include +#include "CFilter.h" + +namespace pglu { +namespace filter { + +namespace { + +char *strichr(const char *str, int chr) { + const char *p = str; + chr = tolower((unsigned char)chr); + for(; tolower((unsigned char)(*p)) != chr; ++p) + if(*p == '\0') + return NULL; + return (char*)p; +} + +char *stristr(const char *str, const char *pattern) { + if(*pattern == '\0') + return (char*)str; + + const char *p = str; + size_t len = strlen(pattern); + for(; (p = strichr(p, pattern[0])) != NULL; ++p) + if(!strnicmp(p, pattern, len)) + return (char*)p; + return NULL; +} + +bool search_and(const char *str, const char *terms, const bool del) { + do { + if(!stristr(str, terms)) + return del; // not found + while(*terms != '\0') + ++terms; + ++terms; + } while(*terms != '\0'); + return !del; // found all +} + +bool search_or(const char *str, const char *terms, const bool del) { + do { + if(stristr(str, terms)) + return !del; // found + while(*terms != '\0') + ++terms; + ++terms; + } while(*terms != '\0'); + return del; // not found +} + +} // namespace + +//-------------------------------------- +// CFilter class +//-------------------------------------- + +CFilter::CFilter() : + m_terms(NULL) +{ +} + +CFilter::CFilter(const char *strFilter, const EFilterMode mode, const bool del) : + m_terms(NULL) +{ + Assign(strFilter, mode, del); +} + +CFilter::~CFilter() { + Clear(); +} + +void CFilter::Assign(const char *strFilter, const EFilterMode mode, const bool del) { + Clear(); + + if(mode == AND) + m_search = search_and; + else if(mode == OR) + m_search = search_or; + else + return; + + m_mode = mode; + m_del = del; + + m_terms = new char[strlen(strFilter) + 2]; + + while(*strFilter == ' ' || *strFilter == '\t') + ++strFilter; + + char *strTerms = m_terms; + while(*strFilter != '\0') { + *(strTerms++) = *(strFilter++); + if(*strFilter == ' ' || *strFilter == '\t') { + *(strTerms++) = '\0'; + do { + ++strFilter; + } while(*strFilter == ' ' || *strFilter == '\t'); + } + } + *strTerms = '\0'; + *(strTerms + 1) = '\0'; +} + +void CFilter::Clear() { + if(m_terms) { + delete[] m_terms; + m_terms = NULL; + } +} + +bool CFilter::IsEmpty() { + if(m_terms) + return *m_terms == '\0'; + else + return true; +} + +bool CFilter::IsMatch(const char *str) { + return m_search(str, m_terms, m_del); +} + +} // namespace filter +} // namespace pglu diff --git a/tool/PGListUtil/src/common/CFilter.h b/tool/PGListUtil/src/common/CFilter.h new file mode 100644 index 00000000..5f52db28 --- /dev/null +++ b/tool/PGListUtil/src/common/CFilter.h @@ -0,0 +1,34 @@ +#ifndef CFILTER_H +#define CFILTER_H + +namespace pglu { +namespace filter { + +typedef enum _EFilterMode { + AND, + OR +} EFilterMode; + +class CFilter { +private: + char * m_terms; + EFilterMode m_mode; + bool m_del; + + bool (* m_search)(const char *, const char *, const bool); + +public: + CFilter(); + CFilter(const char *strFilter, const EFilterMode mode, const bool del); + ~CFilter(); + + void Assign(const char *strFilter, const EFilterMode mode, const bool del); + void Clear(); + bool IsEmpty(); + bool IsMatch(const char *str); +}; + +} // namespace filter +} // namespace pglu + +#endif // CFILTER_H diff --git a/tool/PGListUtil/src/common/CIpList.cpp b/tool/PGListUtil/src/common/CIpList.cpp new file mode 100644 index 00000000..b9eaf800 --- /dev/null +++ b/tool/PGListUtil/src/common/CIpList.cpp @@ -0,0 +1,355 @@ +#include +#include +#include "CIpList.h" + +namespace pglu { +namespace ip { + +namespace { + +inline void Ip_Swap(CIp **ipA, CIp **ipB) { + CIp *ip = *ipA; + *ipA = *ipB; + *ipB = ip; +} + +void Ip_SortByIpQuick(CIp **ipBegin, CIp **ipEnd) { + CIp **ipA; + CIp **ipB; + int nGap = ipEnd - ipBegin; + + if(nGap < 64) + return; + + ipA = ipBegin + ((int)(nGap / 2)); + if((*ipBegin)->ip64 > (*ipA)->ip64) + Ip_Swap(ipBegin, ipA); + if((*ipBegin)->ip64 > (*ipEnd)->ip64) + Ip_Swap(ipBegin, ipEnd); + if((*ipA)->ip64 > (*ipEnd)->ip64) + Ip_Swap(ipA, ipEnd); + ulong ip64 = (*ipA)->ip64; + + ipB = ipEnd - 1; + Ip_Swap(ipA, ipB); + ipA = ipBegin; + + for(; ; ) { + while((*(++ipA))->ip64 < ip64); + while((*(--ipB))->ip64 > ip64); + if(ipA > ipB) + break; + Ip_Swap(ipA, ipB); + } + Ip_Swap(ipA, ipEnd - 1); + + Ip_SortByIpQuick(ipBegin, ipB); + Ip_SortByIpQuick(ipA + 1, ipEnd); +} + +void Ip_SortByIpInsert(CIp **ipBegin, CIp **ipEnd) { + CIp **ipA = ipBegin + 1; + CIp **ipB; + CIp **ipAEnd = ipEnd + 1; + CIp **ipBEnd = ipBegin - 1; + ulong ip64; + for(; ipA != ipAEnd; ++ipA) { + ip64 = (*ipA)->ip64; + for(ipB = ipA - 1; ipB != ipBEnd && (*ipB)->ip64 > ip64; --ipB) + Ip_Swap(ipB, ipB + 1); + } +} + +void Ip_SortByIp(CIp **ipBegin, CIp **ipEnd) { + Ip_SortByIpQuick(ipBegin, ipEnd); + Ip_SortByIpInsert(ipBegin, ipEnd); +} + +CIp * Ip_SortByCaption(CIp *ipHeadA) { + if(!ipHeadA || !(ipHeadA->next)) + return ipHeadA; + + // split ipBを2倍で進めることでipAを中間位置に持っていく + CIp *ipA = ipHeadA; + CIp *ipB = ipHeadA->next->next; + while(ipB) { + ipA = ipA->next; + ipB = ipB->next; + if(ipB) + ipB = ipB->next; + } + CIp *ipHeadB = ipA->next; + ipA->next = NULL; + + ipHeadA = Ip_SortByCaption(ipHeadA); + ipHeadB = Ip_SortByCaption(ipHeadB); + + // merge + CIp ipMerged; + ipA = &ipMerged; + while(ipHeadA || ipHeadB) { + if(((ipHeadA && ipHeadB) && stricmp(ipHeadA->caption, ipHeadB->caption) <= 0) || !ipHeadB) { + ipA->next = ipHeadA; + ipHeadA = ipHeadA->next; + } else { + ipA->next = ipHeadB; + ipHeadB = ipHeadB->next; + } + ipA = ipA->next; + } + ipA->next = NULL; + + return ipMerged.next; +} + +} // namespace + +//-------------------------------------- +// CIpList class +//-------------------------------------- + +CIpList::CIpList() : + m_poolIp(sizeof(CIp)), + m_ipFoot(&m_ipHead), + m_count(0), + m_countDisabled(0) +{ + m_ipHead.caption = NULL; + m_ipHead.ip64 = 0L; + m_ipHead.next = NULL; +} + +CIpList::~CIpList() { + Clear(); +} + +void CIpList::Clear() { + for(CIp *ip = m_ipHead.next; ip; ip = ip->next) + delete[] ip->caption; + m_poolIp.purge_memory(); + m_ipHead.next = NULL; + m_ipFoot = &m_ipHead; + m_count = 0; + m_countDisabled = 0; + UnSetFilter(); +} + +void CIpList::SetFilter(const char *filter, const filter::EFilterMode mode, const bool del) { + m_filter.Assign(filter, mode, del); +} + +void CIpList::UnSetFilter() { + m_filter.Clear(); +} + +CIp * CIpList::CreateIp(boost::xpressive::cmatch & match) { + CIp *ip = (CIp*)m_poolIp.malloc(); + + const char *capBegin = match.prefix().first; + const char *capEnd = match[9].first; + size_t lenCap = capEnd - capBegin; + char *chunk = new char[lenCap + 1]; + memcpy(chunk, capBegin, lenCap); + *(chunk + lenCap) = '\0'; + ip->caption = chunk; + + uchar *ip8 = ip->ip8; + ip8[4] = ParseDigit3(match[4].first, match[4].second); + ip8[5] = ParseDigit3(match[3].first, match[3].second); + ip8[6] = ParseDigit3(match[2].first, match[2].second); + ip8[7] = ParseDigit3(match[1].first, match[1].second); + + if(*(match[10].first) == '-') { + ip8[0] = ParseDigit3(match[8].first, match[8].second); + ip8[1] = ParseDigit3(match[7].first, match[7].second); + ip8[2] = ParseDigit3(match[6].first, match[6].second); + ip8[3] = ParseDigit3(match[5].first, match[5].second); + } else { + ip->ip32[0] = ip->ip32[1] | (0xFFFFFFFF >> ParseDigit3(match[11].first, match[11].second)); + } + + return ip; +} + +bool CIpList::LoadListFile(const char *path) { + char buf[PGLU_LENGTH_FILELINE]; + char colon; + char *colon_p; + + using namespace boost::xpressive; + + static cmatch match; + static mark_tag tagIp1(1), tagIp2(2), tagIp3(3), tagIp4(4), tagIp5(5), tagIp6(6), tagIp7(7), tagIp8(8); + static mark_tag tagColon(9), tagSep(10), tagMask(11); + + static cregex reSyntax = // bos >> (tag = *_) >> // slower + (tagColon = as_xpr(':')) >> *_s >> + (tagIp1 = repeat<1, 3>(_d)) >> as_xpr('.') >> + (tagIp2 = repeat<1, 3>(_d)) >> as_xpr('.') >> + (tagIp3 = repeat<1, 3>(_d)) >> as_xpr('.') >> + (tagIp4 = repeat<1, 3>(_d)) >> + *_s >> (tagSep = as_xpr('-')) >> *_s >> + (tagIp5 = repeat<1, 3>(_d)) >> as_xpr('.') >> + (tagIp6 = repeat<1, 3>(_d)) >> as_xpr('.') >> + (tagIp7 = repeat<1, 3>(_d)) >> as_xpr('.') >> + (tagIp8 = repeat<1, 3>(_d)) >> + *_s >> (_ln | eos); + + static cregex reSyntaxRestorable = + (tagColon = !as_xpr(':')) >> *_s >> + (tagIp1 = repeat<1, 3>(_d)) >> (set = '.', ',') >> + (tagIp2 = repeat<1, 3>(_d)) >> (set = '.', ',') >> + (tagIp3 = repeat<1, 3>(_d)) >> (set = '.', ',') >> + (tagIp4 = repeat<1, 3>(_d)) >> *_s >> ( + (tagSep = +as_xpr('-')) >> *_s >> + (tagIp5 = repeat<1, 3>(_d)) >> (set = '.', ',') >> + (tagIp6 = repeat<1, 3>(_d)) >> (set = '.', ',') >> + (tagIp7 = repeat<1, 3>(_d)) >> (set = '.', ',') >> + (tagIp8 = repeat<1, 3>(_d)) + | + (tagSep = +(set = '/', '\\')) >> *_s >> + (tagMask = repeat<1, 2>(_d)) + ) >> *_s >> (_ln | eos); + + FILE *fp = fopen(path, "r"); + if(fp == NULL) + return false; + + CIp *ip = m_ipFoot; + + if(m_filter.IsEmpty()) { + while(fgets(buf, PGLU_LENGTH_FILELINE, fp)) { + + if(regex_search(buf, match, reSyntax) || regex_search(buf, match, reSyntaxRestorable)) { + ++m_count; + ip->next = CreateIp(match); + ip = ip->next; + } +#ifdef __MINGW32__ + ZeroString(buf); +#endif + } + } else { + while(fgets(buf, PGLU_LENGTH_FILELINE, fp)) { + + if(regex_search(buf, match, reSyntax) || regex_search(buf, match, reSyntaxRestorable)) { + colon_p = (char*)(match[9].first); + colon = *colon_p; + *colon_p = '\0'; + + if(m_filter.IsMatch(buf)) { + ++m_count; + ip->next = CreateIp(match); + ip = ip->next; + } + *colon_p = colon; + } +#ifdef __MINGW32__ + ZeroString(buf); +#endif + } + } + fclose(fp); + ip->next = NULL; + m_ipFoot = ip; + return true; +} + +bool CIpList::SaveListFile(const char *path, const bool append) { + uchar *ip8; + + FILE *fp = fopen(path, (append ? "a" : "w")); + if(fp == NULL) + return false; + + for(CIp *ip = m_ipHead.next; ip; ip = ip->next) { + // IPが0Lなら書き出さない + if(ip->ip64 != 0L) { + ip8 = ip->ip8; + fprintf(fp, + "%s:%u.%u.%u.%u-%u.%u.%u.%u\n", + ip->caption, + ip8[7], ip8[6], ip8[5], ip8[4], + ip8[3], ip8[2], ip8[1], ip8[0] + ); + } + } + fclose(fp); + return true; +} + +void CIpList::CheckAndSort(const bool sortCap, const bool sortIp, const bool delDupIp) { + CIp **ipBegin; + CIp **ipEnd; + CIp *ip; + + if(m_count < 2) + return; + + if(sortIp || delDupIp) { + // リストから配列を複製 + CIp **ipSort = new CIp*[m_count]; + ipBegin = ipSort; + for(ip = m_ipHead.next; ip; ip = ip->next) + *(ipBegin++) = ip; + + // 配列をソート + Ip_SortByIp(ipSort, ipSort + m_count - 1); + + if(delDupIp) { + // すでにIPが0Lなものを無効としてカウント + ipBegin = ipSort; + ipEnd = ipBegin + m_count; + + for(; ipBegin != ipEnd && (*ipBegin)->ip64 == 0L; ++ipBegin) + ++m_countDisabled; + if(ipBegin == ipEnd) + goto END_SORT; // 全てのIPが0L + + // 重複したIPは0Lにして無効としてカウント + for(--ipEnd; ipBegin != ipEnd; ++ipBegin) + if((*ipBegin)->ip64 == (*(ipBegin + 1))->ip64) { + (*ipBegin)->ip64 = 0L; + ++m_countDisabled; + } + } + if(sortIp) { + // 配列の中身を連結 + ipBegin = ipSort; + ipEnd = ipSort + m_count; + ip = &m_ipHead; + while(ipBegin != ipEnd) { + ip->next = *(ipBegin++); + ip = ip->next; + } + ip->next = NULL; + } + END_SORT: + delete[] ipSort; + } + + if(sortCap) + m_ipHead.next = Ip_SortByCaption(m_ipHead.next); + + if(sortIp || sortCap) { + // m_ipFootを再設定 + ip = m_ipHead.next; + if(ip) { + for(; ip->next; ip = ip->next); + m_ipFoot = ip; + } else { + m_ipFoot = &m_ipHead; + } + } +} + +int CIpList::Count() { + return m_count; +} + +int CIpList::CountDisabled() { + return m_countDisabled; +} + +} // namespace ip +} // namespace pglu