修改目录结构

This commit is contained in:
2024-10-16 10:00:47 +08:00
parent 82b400b45c
commit 7b1e27db87
16 changed files with 27 additions and 13 deletions

381
qqwry/qqwry.c Normal file
View File

@@ -0,0 +1,381 @@
#include "qqwry.h"
ip_data ip_defaults = {.parent_data = NULL,.child_data = NULL,.index_size = 7,.isp = 1 };
int qqwry_init(char *file)
{
int buff;
ip_defaults.fp = fopen(file, "r");
if (ip_defaults.fp == NULL) {
fprintf(stderr, "failed to open %s\n", file);
return -1;
}
readvalue(4, &buff); //first 4 bytes represents the offset of first index
ip_defaults.first_item = buff;
readvalue(4, &buff);
ip_defaults.last_item = buff;
ip_defaults.item_number = (ip_defaults.last_item - ip_defaults.first_item) / ip_defaults.index_size;
return 0;
}
int qqwry_match(char *pattern, char *subject)
{
regex_t regex;
int reti, ret;
char msgbuf[100];
/* Compile regular expression */
reti = regcomp(&regex, pattern, 0);
if (reti) {
fprintf(stderr, "Could not compile regex\n");
return 0;
}
/* Execute regular expression */
reti = regexec(&regex, subject, 0, NULL, 0);
if (!reti) {
ret = 1;
} else if (reti == REG_NOMATCH) {
ret = 0;
} else {
regerror(reti, &regex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
ret = 0;
}
/* Free memory allocated to the pattern buffer by regcomp() */
regfree(&regex);
return ret;
}
iconv_t initialize_iconv(const char *target, const char *src) {
// 创建转换描述符
iconv_t iconvDesc = iconv_open(target, src);
// 检查 iconv_open 是否成功
if (iconvDesc == (iconv_t) - 1) {
// 如果失败,打印错误信息并返回 NULL
fprintf(stderr, "Error: Conversion from '%s' to '%s' is not available.\n", src, target);
return (iconv_t)NULL;
}
// 成功时返回 iconv_t 描述符
return iconvDesc;
}
int gbk2utf8(char *utf8_str, char *gbk_str)
{
iconv_t iconvDesc = initialize_iconv("UTF-8//TRANSLIT//IGNORE", "GBK");
size_t iconv_value, len, utf8len;
//int len_start;
len = strlen(gbk_str) + 1;
if (!len) {
fprintf(stderr, "iconvISO2UTF8: input String is empty.");
return -1;
}
/* Assign enough space to put the UTF-8. */
utf8len = 3 * len;
if (!utf8_str) {
fprintf(stderr, "iconvISO2UTF8: Calloc failed.");
return -1;
}
iconv_value = iconv(iconvDesc, &gbk_str, &len, &utf8_str, &utf8len);
/* Handle failures. */
if (iconv_value == (size_t)-1) {
switch (errno) {
/* See "man 3 iconv" for an explanation. */
case EILSEQ:
fprintf(stderr, "iconv failed: Invalid multibyte sequence, in string '%s', length %d, out string '%s', length %d\n", gbk_str, (int)len, utf8_str, (int)utf8len);
break;
case EINVAL:
fprintf(stderr, "iconv failed: Incomplete multibyte sequence, in string '%s', length %d, out string '%s', length %d\n", gbk_str, (int)len, utf8_str, (int)utf8len);
break;
case E2BIG:
fprintf(stderr, "iconv failed: No more room, in string '%s', length %d, out string '%s', length %d\n", gbk_str, (int)len, utf8_str, (int)utf8len);
break;
default:
fprintf(stderr, "iconv failed, in string '%s', length %d, out string '%s', length %d\n", gbk_str, (int)len, utf8_str, (int)utf8len);
}
return -1;
}
if (iconv_close(iconvDesc) != 0) {
fprintf(stderr, "libicon close failed: %s", strerror(errno));
return -1;
}
return utf8len;
}
int readbyte(int size, int offset, int *buff)
{
int count;
int nbytes = 1;
*buff = 0;
if (ip_defaults.fp != NULL) {
//if offset is negative,keep the current offset unchanged
if (offset >= 0) {
qqwry_seek(offset);
} else {
int curr_pos = ftell(ip_defaults.fp);
fseek(ip_defaults.fp, curr_pos, SEEK_SET);
}
if ((count = fread(buff, nbytes, size, ip_defaults.fp)) != size) {
return -1;
}
return count;
}
return -1;
}
int readvalue(unsigned int size, int *buff)
{
return readbyte(size, -1, buff);
}
void set_ip_range(unsigned int offset)
{
readbyte(4, offset, (int *)(&ip_defaults.startip));
//skip 3 bytes to read the next ip
qqwry_forward(3);
readvalue(4, (int *)(&ip_defaults.endip));
}
void qqwry_seek(int offset)
{
fseek(ip_defaults.fp, offset, SEEK_SET);
}
void qqwry_forward(unsigned int byte)
{
fseek(ip_defaults.fp, byte, SEEK_CUR);
}
void qqwry_back(unsigned int byte)
{
int currPos = ftell(ip_defaults.fp);
qqwry_seek(currPos - byte);
}
char *long2ip(int ip) {
// 分配16字节内存用于存储IP字符串
char *ip_str = malloc(16 * sizeof(char));
if (ip_str == NULL) {
// 如果内存分配失败返回NULL
fprintf(stderr, "Memory allocation failed\n");
return NULL;
}
// 将IP转换为字符串
snprintf(ip_str, 16, "%d.%d.%d.%d",
(ip >> 24) & 0xFF,
(ip >> 16) & 0xFF,
(ip >> 8) & 0xFF,
ip & 0xFF);
return ip_str;
}
unsigned int ip2long(char *ip)
{
int nip = 0, tmp = 0, step = 24;
char *copy = strdup(ip);
char *token = strtok(copy, ".");
while (token) {
tmp = (unsigned int)atoi(token);
tmp <<= step;
nip += tmp;
step -= 8;
token = strtok(NULL, ".");
}
free(copy);
return nip;
}
int search_record(char *ip)
{
int numeric_ip = ip2long(ip);
int low = 0;
int high = ip_defaults.item_number;
return binary_search(low, high, numeric_ip);
}
int binary_search(int low, int high, int ip)
{
unsigned int mid, offset, startip, endip;
if (low <= high) {
mid = low + (high - low) / 2;
offset = round(ip_defaults.first_item + mid * ip_defaults.index_size);
set_ip_range(offset);
startip = ip_defaults.startip;
endip = ip_defaults.endip;
if (ip >= startip && ip <= endip) {
return offset;
}
//if ip is below the lower limit, decrease the upper limit
if (ip < startip) {
return binary_search(low, mid - 1, ip);
}
//if ip is above the lower limit, increase the lower limit
return binary_search(mid + 1, high, ip);
}
return ip_defaults.last_item;
}
static char *get_string()
{
unsigned int buff = 0;
char *str = realloc(NULL, sizeof(char));
char *tmp;
int i = 0, c = 0;
if ((c = readvalue(1, (int *)(&buff))) != 1) {
return NULL;
}
for (i = 0; buff != 0; i++) {
str[i] = buff;
tmp = realloc(str, (sizeof(char)) * (i + 2));
str = tmp;
readvalue(1, (int *)(&buff));
}
str[i] = '\0';
return str;
}
static char *get_child_data()
{
unsigned int flag, offset;
readvalue(1, (int *)(&flag));
if (flag == 0) { //no child data
return 0;
} else if (flag == 1 || flag == 2) { // redirection for child data
readvalue(3, (int *)(&offset));
qqwry_seek(offset);
return get_string();
}
// no redirection for child data
qqwry_back(1);
return get_string();
}
int convert_data(char *parent_data, char *child_data)
{
ip_defaults.parent_data = malloc(strlen(parent_data) * 3); //in utf8,one chinese character could consume up to 3 bytes
gbk2utf8(ip_defaults.parent_data, parent_data);
ip_defaults.child_data = malloc(strlen(child_data) * 3);
gbk2utf8(ip_defaults.child_data, child_data);
if (qqwry_match("移动", ip_defaults.child_data)) {
ip_defaults.isp = 0x03;
} else if (qqwry_match("联通", ip_defaults.child_data)) {
ip_defaults.isp = 0x02;
} else {
ip_defaults.isp = 0x01;
}
free(parent_data);
free(child_data);
return 0;
}
int qqwry_redirect(int bytes)
{
int redirect_offset;
readvalue(bytes, &redirect_offset);
qqwry_seek(redirect_offset);
return redirect_offset;
}
int get_data(int offset)
{ //get record data
int flag, redirect_offset;
char *parent_data, *child_data;
readbyte(1, offset + 4, &flag); //get the flag value to see if the data is stored elsewhere
if (flag == 1) { //this means we should look elsewhere for both
redirect_offset = qqwry_redirect(3); //read 3 bytes to get a new offset and redirect there
readvalue(1, &flag);
if (flag == 2) {
// child data is elsewhere
qqwry_redirect(3);
parent_data = get_string();
qqwry_seek(redirect_offset + 4);
child_data = get_child_data();
} else { // no redirection for parent data
qqwry_back(1);
parent_data = get_string();
child_data = get_child_data();
}
} else if (flag == 2) { //redirection for only parent
qqwry_redirect(3);
parent_data = get_string();
qqwry_seek(offset + 8);
child_data = get_child_data();
} else { // no redirection for both parent and child
qqwry_back(1);
parent_data = get_string();
child_data = get_string();
}
convert_data(parent_data, child_data);
return 0;
}
int get_location(char *ip)
{
//offset is the address where the ip is found. first 4 bytes is the start ip address of the ip range and the following 3 bytes is the offset pointing to the actual record data;
unsigned int offset = search_record(ip);
unsigned int tmp_offset;
qqwry_seek(offset + 4); // skip 4 byte to get the offset value pointing to record data
readvalue(3, (int *)(&tmp_offset)); // the offset pointing to the data
get_data(tmp_offset);
return 0;
}
char *qqwry_(char *ip)
{
char *qqdb_path = "qqwry.dat";
if (access(qqdb_path, F_OK) == -1) { // 判断 ip2region 地址定位库是否存在
qqdb_path = "qqwry/qqwry.dat";
if (access(qqdb_path, F_OK) == -1) {
printf("qqwry.dat DOESN'T EXIST!\n");
return NULL;
}
}
qqwry_init("qqwry.dat");
get_location(ip);
//printf("%s-%s %d\n", ip_defaults.parent_data, ip_defaults.child_data, ip_defaults.isp);
//printf("QQWRY %s %s-%s\n", ip, ip_defaults.parent_data, ip_defaults.child_data);
// 计算拼接后的字符串所需的长度
size_t len = strlen(ip_defaults.parent_data) + strlen(ip_defaults.child_data) + 2; // +2 for the hyphen and null terminator
char *result = malloc(len);
if (result) {
// 拼接字符串,格式为 "parent_data-child_data"
snprintf(result, len, "%s-%s", ip_defaults.parent_data, ip_defaults.child_data);
}
free(ip_defaults.parent_data);
free(ip_defaults.child_data);
fclose(ip_defaults.fp);
return result;
}

BIN
qqwry/qqwry.dat Normal file

Binary file not shown.

31
qqwry/qqwry.h Normal file
View File

@@ -0,0 +1,31 @@
#include <unistd.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <math.h>
#include <stdio.h>
#include <iconv.h>
#include <errno.h>
#include <regex.h>
typedef struct {
FILE *fp;
unsigned int index_size;
unsigned int first_item, last_item;
unsigned int item_number, startip, endip, curr_data_offset;
char *parent_data, *child_data;
int isp;
} ip_data;
int search_record(char *ip);
int binary_search(int low, int high, int ip);
int readbyte(int size, int offset, int *buff);
int readvalue(unsigned int size, int *buff);
void qqwry_seek(int offset);
void qqwry_forward(unsigned int byte);
void qqwry_back(unsigned int byte);
int get_location(char *ip);
int gbk2utf8(char *utf8_str, char *gbk_str);
extern char *qqwry_(char *ip);

BIN
qqwry/qqwry.o Normal file

Binary file not shown.