diff options
author | iroul <iroul@iroul-VirtualBox.(none)> | 2014-04-04 07:35:14 -0700 |
---|---|---|
committer | iroul <iroul@iroul-VirtualBox.(none)> | 2014-04-04 07:35:14 -0700 |
commit | afd34f2893a06a3aecf17e8e83b1df6ed2ae91a2 (patch) | |
tree | 851102abc55d91a1b76e63e9e89f9a7733da95b5 /src/utilities/fqterm_ip_location.cpp | |
parent | c4b028ad53f7b362a864de24828d7cc39ff67b0a (diff) | |
download | fqterm-afd34f2893a06a3aecf17e8e83b1df6ed2ae91a2.tar.xz |
move to my github.
Diffstat (limited to 'src/utilities/fqterm_ip_location.cpp')
-rw-r--r-- | src/utilities/fqterm_ip_location.cpp | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/src/utilities/fqterm_ip_location.cpp b/src/utilities/fqterm_ip_location.cpp new file mode 100644 index 0000000..ea5946d --- /dev/null +++ b/src/utilities/fqterm_ip_location.cpp @@ -0,0 +1,265 @@ +/*************************************************************************** + * fqterm, a terminal emulator for both BBS and *nix. * + * Copyright (C) 2008 fqterm development group. * + * * + * 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., * + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * + ***************************************************************************/ + +#include <QString> +#include <QRegExp> +#include <QDir> +#include <QStringList> +#include <ctype.h> + +#ifdef Q_OS_WIN32 +#include <winsock2.h> +#else +#include <netinet/in.h> +#include <arpa/inet.h> +#endif + +#include "fqterm_trace.h" +#include "fqterm_ip_location.h" +#include "fqterm_path.h" +#include "fqterm.h" + +namespace FQTerm { + +FQTermIPLocation* FQTermIPLocation::instance_ = NULL; + +FQTermIPLocation::FQTermIPLocation(const QString &pathLib) { + ipDatabase_ = new IPDatabase; + ipDatabase_->ipfp = NULL; + + isFileExiting_ = true; + + //case-insensitive match + QDir dir(pathLib); + QStringList files = dir.entryList(QStringList( + "[Qq][Qq][Ww][Rr][Yy].[Dd][Aa][Tt]"), QDir::Files); + if (!files.isEmpty()) { + if ((ipDatabase_->ipfp = fopen((pathLib + (files.at(0))).toLocal8Bit(), "rb")) == NULL) { + FQ_TRACE("iplocation", 0) << "Can't open ip database file!"; + isFileExiting_ = false; + } + } else { + isFileExiting_ = false; + } + +} + +FQTermIPLocation::~FQTermIPLocation() { + if (ipDatabase_->ipfp != NULL) { + fclose(ipDatabase_->ipfp); + } + delete ipDatabase_; +} + +uint32 FQTermIPLocation::byteArrayToInt(char *ip, int count) { + uint32 tmp, ret = 0L; + if (count < 1 || count > 4) { + FQ_TRACE("iplocation", 0) << "byteArrayToInt() error!"; + return 0; + } + for (int i = 0; i < count; i++) { + tmp = ((uint32)ip[i]) &0x000000FF; + ret |= (tmp << (8 *i)); + } + return ret; +} + +void FQTermIPLocation::readFrom(FILE *fp, uint32 offset, char *buf, int len) { + if (fseek(fp, (long)offset, SEEK_SET) == -1) { + FQ_TRACE("iplocation", 0) << "readFrom() error 1"; + memset(buf, 0, len); + return ; + } + if (fread(buf, sizeof(char), len, fp) == 0) { + FQ_TRACE("iplocation", 0) << "readFrom() error 2"; + memset(buf, 0, len); + return ; + } + return ; +} + +int FQTermIPLocation::readLineFrom(FILE *fp, uint32 offset, QByteArray &ret_str) { + char str[512]; + if (fseek(fp, (long)offset, SEEK_SET) == -1) { + FQ_TRACE("iplocation", 0) << "readLineFrom error 1"; + ret_str = QByteArray(); + return -1; + } + if (fgets((char*)str, 512, fp) == NULL) { + FQ_TRACE("iplocation", 0) << "readLineFrom error 2"; + ret_str = QByteArray(); + return -1; + } + ret_str = QByteArray(str); + return (ret_str.length()); +} + +uint32 FQTermIPLocation::getString(FILE *fp, uint32 offset, uint32 lastoffset, + QByteArray &ret, unsigned int flag, int maxRecursiveDepth) { + if (maxRecursiveDepth <= 0) + return 0; + unsigned int fg; + if (fp == NULL) { + return 0; + } + char buf[3] = {0}; + readFrom(fp, offset, buf, 1); + if (buf[0] == 0x01 || buf[0] == 0x02) { + fg = buf[0]; + readFrom(fp, offset + 1, buf, 3); + return getString(fp, byteArrayToInt(buf, 3), offset, ret, fg, maxRecursiveDepth - 1); + } else { + readLineFrom(fp, offset, ret); + } + switch (flag) { + case 0x01: + return 0; + case 0x02: + return lastoffset + 4; + default: + return offset + ret.length() + 1; + } +} + + +void FQTermIPLocation::getCountryCity(FILE *fp, uint32 offset, QByteArray &country, + QByteArray &city) { + uint32 next_offset; + if (fp == NULL) { + return ; + } + next_offset = getString(fp, offset, 0L, country, 0); + if (next_offset == 0) { + city = ""; + } else { + getString(fp, next_offset, 0L, city, 0); + } + return ; +} + +void FQTermIPLocation::setIpRange(int rec_no, IPDatabase *f) { + uint32 offset; + if (f == NULL) { + return ; + } + char buf[7] = {0}; + offset = f->offset_first_start_ip + rec_no * 7; + readFrom(f->ipfp, offset, buf, 7); + f->cur_start_ip = byteArrayToInt(buf, 4); + f->offset_cur_end_ip = byteArrayToInt(buf + 4, 3); + + readFrom(f->ipfp, f->offset_cur_end_ip, buf, 4); + f->cur_end_ip = byteArrayToInt(buf, 4); + +} + +bool FQTermIPLocation::getLocation(QString &url, QString &country, QString &city) +{ + QByteArray gbCountry, gbCity; + bool result = getLocation(url, gbCountry, gbCity); + country = encoding2unicode(gbCountry, FQTERM_ENCODING_GBK); + city = encoding2unicode(gbCity, FQTERM_ENCODING_GBK); + return result; +} + +bool FQTermIPLocation::getLocation(QString &url, QByteArray &country, + QByteArray &city) { + int rec, record_count, B, E; + uint32 ip; +#ifdef Q_OS_WIN32 + uint32 ipValue = inet_addr((const char*)url.toLatin1()); +#else + in_addr_t ipValue = inet_addr((const char*)url.toLatin1()); +#endif + if ((int)ipValue == -1) { + return false; + } else { + ip = ntohl(ipValue); + } + + char buf[4] = {0}; + readFrom(ipDatabase_->ipfp, 0L, (char*)buf, 4); + ipDatabase_->offset_first_start_ip = byteArrayToInt((char*)buf, 4); + readFrom(ipDatabase_->ipfp, 4L, (char*)buf, 4); + ipDatabase_->offset_last_start_ip = byteArrayToInt((char*)buf, 4); + + record_count = (ipDatabase_->offset_last_start_ip - ipDatabase_->offset_first_start_ip) / 7; + if (record_count <= 1) { + return FALSE; + } + + // search for right range + B = 0; + E = record_count; + while (B < E-1) { + rec = (B + E) / 2; + setIpRange(rec, ipDatabase_); + if (ip == ipDatabase_->cur_start_ip) { + B = rec; + break; + } + if (ip > ipDatabase_->cur_start_ip) { + B = rec; + } else { + E = rec; + } + } + setIpRange(B, ipDatabase_); + + if (ipDatabase_->cur_start_ip <= ip && ip <= ipDatabase_->cur_end_ip) { + getCountryCity(ipDatabase_->ipfp, ipDatabase_->offset_cur_end_ip + 4, country, city); + //country.replace( country.find( "CZ88.NET", 0, FALSE ), 8, "" ); + if ((rec = country.toUpper().indexOf("CZ88.NET", 0)) >= 0) { + country.replace(rec, 8, "********"); + } + if ((rec = city.toUpper().indexOf("CZ88.NET", 0)) >= 0) { + city.replace(rec, 8, "********"); + } + + } else { + // not in this range... miss + country = "unkown"; + city = ""; + } + // if ip_start<=ip<=ip_end + return TRUE; +} + +FQTermIPLocation* FQTermIPLocation::getInstance() { + if (instance_ == NULL) { + instance_ = new FQTermIPLocation(getPath(USER_CONFIG)); + if (instance_->isFileExiting_ == NULL) { + delete instance_; + instance_ = new FQTermIPLocation(getPath(RESOURCE)); + if (instance_->isFileExiting_ == NULL) { + delete instance_; + instance_ = NULL; + } + } + } + return instance_; +} + +void FQTermIPLocation::Destroy() { + delete instance_; + instance_ = NULL; +} + +} // namespace FQTerm |