From b3a4f05d9f7f36d4822bbcfce6785f98bc0bf4fa Mon Sep 17 00:00:00 2001 From: katze Date: Wed, 11 Nov 2020 02:46:45 +0100 Subject: Upload files to 'tool/PGListUtil/src/common' --- tool/PGListUtil/src/common/CIpList.cpp | 355 +++++++++++++++++++++++++++++++++ 1 file changed, 355 insertions(+) create mode 100644 tool/PGListUtil/src/common/CIpList.cpp (limited to 'tool/PGListUtil/src/common/CIpList.cpp') 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 -- cgit v1.2.3