comparison src/protocols/qq/ip_location.c @ 14021:ef8490f9e823

[gaim-migrate @ 16618] Replaced all C++-style comments with C-style ones. Cleaned up some comments and implemented a more consistent formatting scheme. committer: Tailor Script <tailor@pidgin.im>
author Mark Huetsch <markhuetsch>
date Wed, 02 Aug 2006 15:35:36 +0000
parents 983fd420e86b
children
comparison
equal deleted inserted replaced
14020:13e7ba964993 14021:ef8490f9e823
22 * This code is based on 22 * This code is based on
23 * * qqwry.c, by lvxiang <srm2003@163.com> 23 * * qqwry.c, by lvxiang <srm2003@163.com>
24 * * IpChecker.m, by Jeff_Ye 24 * * IpChecker.m, by Jeff_Ye
25 */ 25 */
26 26
27 // START OF FILE
28 /*****************************************************************************/
29 #include "internal.h" 27 #include "internal.h"
30 #include <string.h> // memset 28 #include <string.h>
31 #include "debug.h" 29 #include "debug.h"
32 #include "prefs.h" // gaim_prefs_get_string 30 #include "prefs.h"
33 31
34 #include "utils.h" 32 #include "utils.h"
35 #include "ip_location.h" 33 #include "ip_location.h"
36 34
37 #define DEFAULT_IP_LOCATION_FILE "gaim/QQWry.dat" 35 #define DEFAULT_IP_LOCATION_FILE "gaim/QQWry.dat"
38 36
39 typedef struct _ip_finder ip_finder; 37 typedef struct _ip_finder ip_finder;
40 38
41 // all offset is based the begining of the file 39 /* all offset is based the begining of the file */
42 struct _ip_finder { 40 struct _ip_finder {
43 guint32 offset_first_start_ip; // first abs offset of start ip 41 guint32 offset_first_start_ip; /* first abs offset of start ip */
44 guint32 offset_last_start_ip; // last abs offset of start ip 42 guint32 offset_last_start_ip; /* last abs offset of start ip */
45 guint32 cur_start_ip; // start ip of current search range 43 guint32 cur_start_ip; /* start ip of current search range */
46 guint32 cur_end_ip; // end ip of current search range 44 guint32 cur_end_ip; /* end ip of current search range */
47 guint32 offset_cur_end_ip; // where is the current end ip saved 45 guint32 offset_cur_end_ip; /* where is the current end ip saved */
48 GIOChannel *io; // IO Channel to read file 46 GIOChannel *io; /* IO Channel to read file */
49 }; // struct _ip_finder 47 }; /* struct _ip_finder */
50 48
51 /*****************************************************************************/ 49 /* convert 1-4 bytes array to integer.
52 // convert 1-4 bytes array to integer. 50 * Small endian (higher bytes in lower place) */
53 // Small endian (higher bytes in lower place) 51 static guint32 _byte_array_to_int(guint8 *ip, gint count)
54 static guint32 _byte_array_to_int(guint8 * ip, gint count)
55 { 52 {
56 guint32 ret, i; 53 guint32 ret, i;
57 g_return_val_if_fail(count >= 1 && count <= 4, 0); 54 g_return_val_if_fail(count >= 1 && count <= 4, 0);
58 ret = ip[0]; 55 ret = ip[0];
59 for (i = 0; i < count; i++) 56 for (i = 0; i < count; i++)
60 ret |= ((guint32) ip[i]) << (8 * i); 57 ret |= ((guint32) ip[i]) << (8 * i);
61 return ret; 58 return ret;
62 } // _byte_array_to_int 59 }
63 60
64 /*****************************************************************************/ 61 /* read len of bytes to buf, from io at offset */
65 // read len of bytes to buf, from io at offset 62 static void _read_from(GIOChannel *io, guint32 offset, guint8 *buf, gint len)
66 static void _read_from(GIOChannel * io, guint32 offset, guint8 * buf, gint len)
67 { 63 {
68 GError *err; 64 GError *err;
69 GIOStatus status; 65 GIOStatus status;
70 66
71 err = NULL; 67 err = NULL;
73 if (err != NULL) { 69 if (err != NULL) {
74 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Fail seek file @offset[%d]: %s", offset, err->message); 70 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Fail seek file @offset[%d]: %s", offset, err->message);
75 g_error_free(err); 71 g_error_free(err);
76 memset(buf, 0, len); 72 memset(buf, 0, len);
77 return; 73 return;
78 } // if err 74 }
79 75
80 status = g_io_channel_read_chars(io, buf, len, NULL, &err); 76 status = g_io_channel_read_chars(io, buf, len, NULL, &err);
81 if (err != NULL) { 77 if (err != NULL) {
82 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Fail read %d bytes from file: %s", len, err->message); 78 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Fail read %d bytes from file: %s", len, err->message);
83 g_error_free(err); 79 g_error_free(err);
84 memset(buf, 0, len); 80 memset(buf, 0, len);
85 return; 81 return;
86 } // if err 82 }
87 } // _read_from 83 }
88 84
89 /*****************************************************************************/ 85 /* read len of bytes to buf, from io at offset */
90 // read len of bytes to buf, from io at offset 86 static gsize _read_line_from(GIOChannel *io, guint32 offset, gchar **ret_str)
91 static gsize _read_line_from(GIOChannel * io, guint32 offset, gchar ** ret_str)
92 { 87 {
93 gsize bytes_read; 88 gsize bytes_read;
94 GError *err; 89 GError *err;
95 GIOStatus status; 90 GIOStatus status;
96 91
99 if (err != NULL) { 94 if (err != NULL) {
100 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Fail seek file @offset[%d]: %s", offset, err->message); 95 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Fail seek file @offset[%d]: %s", offset, err->message);
101 g_error_free(err); 96 g_error_free(err);
102 ret_str = NULL; 97 ret_str = NULL;
103 return -1; 98 return -1;
104 } // if err 99 }
105 100
106 status = g_io_channel_read_line(io, ret_str, &bytes_read, NULL, &err); 101 status = g_io_channel_read_line(io, ret_str, &bytes_read, NULL, &err);
107 if (err != NULL) { 102 if (err != NULL) {
108 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Fail read from file: %s", err->message); 103 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Fail read from file: %s", err->message);
109 g_error_free(err); 104 g_error_free(err);
110 ret_str = NULL; 105 ret_str = NULL;
111 return -1; 106 return -1;
112 } // if err 107 }
113 108
114 return bytes_read; 109 return bytes_read;
115 } // _read_from 110 }
116 111
117 /*****************************************************************************/ 112 /* read the string from io, at offset, it may jump several times
118 // read the string from io, at offset, it may jump several times 113 * returns the offset of next readable string for area */
119 // returns the offset of next readable string for area 114 static guint32 _get_string(GIOChannel *io, guint32 offset, gchar **ret)
120 static guint32 _get_string(GIOChannel * io, guint32 offset, gchar ** ret)
121 { 115 {
122 guint8 *buf; 116 guint8 *buf;
123 g_return_val_if_fail(io != NULL, 0); 117 g_return_val_if_fail(io != NULL, 0);
124 118
125 buf = g_new0(guint8, 3); 119 buf = g_new0(guint8, 3);
134 _get_string(io, _byte_array_to_int(buf, 3), ret); 128 _get_string(io, _byte_array_to_int(buf, 3), ret);
135 return offset + 4; 129 return offset + 4;
136 default: 130 default:
137 _read_line_from(io, offset, ret); 131 _read_line_from(io, offset, ret);
138 return offset + strlen(*ret) + 1; 132 return offset + strlen(*ret) + 1;
139 } /* switch */ 133 }
140 } // _get_string 134 }
141 135
142 /*****************************************************************************/ 136 /* extract country and area starting from offset */
143 // extract country and area starting from offset 137 static void _get_country_city(GIOChannel *io, guint32 offset, gchar **country, gchar **area)
144 static void _get_country_city(GIOChannel * io, guint32 offset, gchar ** country, gchar ** area)
145 { 138 {
146 guint32 next_offset; 139 guint32 next_offset;
147 g_return_if_fail(io != NULL); 140 g_return_if_fail(io != NULL);
148 141
149 next_offset = _get_string(io, offset, country); 142 next_offset = _get_string(io, offset, country);
150 if (next_offset == 0) 143 if (next_offset == 0)
151 *area = g_strdup(""); 144 *area = g_strdup("");
152 else 145 else
153 _get_string(io, next_offset, area); 146 _get_string(io, next_offset, area);
154 } // _get_country_city 147 }
155 148
156 /*****************************************************************************/ 149 /* set start_ip and end_ip of current range */
157 // set start_ip and end_ip of current range 150 static void _set_ip_range(gint rec_no, ip_finder *f)
158 static void _set_ip_range(gint rec_no, ip_finder * f)
159 { 151 {
160 guint8 *buf; 152 guint8 *buf;
161 guint32 offset; 153 guint32 offset;
162 154
163 g_return_if_fail(f != NULL); 155 g_return_if_fail(f != NULL);
169 f->cur_start_ip = _byte_array_to_int(buf, 4); 161 f->cur_start_ip = _byte_array_to_int(buf, 4);
170 f->offset_cur_end_ip = _byte_array_to_int(buf + 4, 3); 162 f->offset_cur_end_ip = _byte_array_to_int(buf + 4, 3);
171 163
172 _read_from(f->io, f->offset_cur_end_ip, buf, 4); 164 _read_from(f->io, f->offset_cur_end_ip, buf, 4);
173 f->cur_end_ip = _byte_array_to_int(buf, 4); 165 f->cur_end_ip = _byte_array_to_int(buf, 4);
174 166 }
175 } // _set_ip_range 167
176 168 /* set the country and area for given IP.
177 /*****************************************************************************/ 169 * country and area needs to be freed later */
178 // set the country and area for given IP. 170 gboolean qq_ip_get_location(guint32 ip, gchar **country, gchar **area)
179 // country and area needs to be freed later
180 gboolean qq_ip_get_location(guint32 ip, gchar ** country, gchar ** area)
181 { 171 {
182 gint rec, record_count, B, E; 172 gint rec, record_count, B, E;
183 guint8 *buf; 173 guint8 *buf;
184 gchar *addr_file; 174 gchar *addr_file;
185 ip_finder *f; 175 ip_finder *f;
202 g_free(addr_file); 192 g_free(addr_file);
203 if (err != NULL) { 193 if (err != NULL) {
204 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Unable to open (%s): %s\n", addr_file, err->message); 194 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Unable to open (%s): %s\n", addr_file, err->message);
205 g_error_free(err); 195 g_error_free(err);
206 return FALSE; 196 return FALSE;
207 } else 197 } else {
208 g_io_channel_set_encoding(f->io, NULL, NULL); // set binary 198 g_io_channel_set_encoding(f->io, NULL, NULL); /* set binary */
199 }
209 200
210 buf = g_newa(guint8, 4); 201 buf = g_newa(guint8, 4);
211 202
212 _read_from(f->io, 0, buf, 4); 203 _read_from(f->io, 0, buf, 4);
213 f->offset_first_start_ip = _byte_array_to_int(buf, 4); 204 f->offset_first_start_ip = _byte_array_to_int(buf, 4);
218 if (record_count <= 1) { 209 if (record_count <= 1) {
219 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "File data error, no records found\n"); 210 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "File data error, no records found\n");
220 g_io_channel_shutdown(f->io, FALSE, NULL); 211 g_io_channel_shutdown(f->io, FALSE, NULL);
221 return FALSE;; 212 return FALSE;;
222 } 213 }
223 // search for right range 214 /* search for right range */
224 B = 0; 215 B = 0;
225 E = record_count; 216 E = record_count;
226 while (B < E - 1) { 217 while (B < E - 1) {
227 rec = (B + E) / 2; 218 rec = (B + E) / 2;
228 _set_ip_range(rec, f); 219 _set_ip_range(rec, f);
232 } 223 }
233 if (ip > f->cur_start_ip) 224 if (ip > f->cur_start_ip)
234 B = rec; 225 B = rec;
235 else 226 else
236 E = rec; 227 E = rec;
237 } // while 228 }
238 _set_ip_range(B, f); 229 _set_ip_range(B, f);
239 230
240 if (f->cur_start_ip <= ip && ip <= f->cur_end_ip) { 231 if (f->cur_start_ip <= ip && ip <= f->cur_end_ip) {
241 _get_country_city(f->io, f->offset_cur_end_ip + 4, country, area); 232 _get_country_city(f->io, f->offset_cur_end_ip + 4, country, area);
242 } else { // not in this range... miss 233 } else { /* not in this range... miss */
243 *country = g_strdup("unkown"); 234 *country = g_strdup("unkown");
244 *area = g_strdup(" "); 235 *area = g_strdup(" ");
245 } // if ip_start<=ip<=ip_end 236 } /* if ip_start<=ip<=ip_end */
246 237
247 g_io_channel_shutdown(f->io, FALSE, NULL); 238 g_io_channel_shutdown(f->io, FALSE, NULL);
248 return TRUE; 239 return TRUE;
249 240 }
250 } // qq_ip_get_location
251
252 /*****************************************************************************/
253 // END OF FILE