순수 IP 데이터베이스 분석 Delphi D10.1 일반 사용

46096 단어
하나의 단원으로 코드를 공유합니다.
 
  1 unit   Net.IPLocation;
  2 
  3 interface
  4 
  5 uses System.Classes, System.SysUtils, Winapi.WinSock, Vcl.Forms,
  6   System.Math, System.SyncObjs;
  7 
  8 type
  9   TIPLocation = class(TObject)
 10   private
 11     QQWryFileName: string;
 12     QQWryFileStream: TBufferedFileStream;
 13     QQWryFileSize: Cardinal;
 14     IPRecordNum: Cardinal;
 15     FirstIPIndexOffset, LastIPIndexOffset: Cardinal;
 16     FLock: TCriticalSection;
 17 
 18     function GetQQWryFileName: string;
 19     function GetQQWryFileSize: Cardinal;
 20     function GetIPRecordNum: Cardinal;
 21     function GetQQWryDate: TDate;
 22     function GetQQWryDataFrom: string;
 23     function GetIPLocation(IPLocationOffset: Cardinal): TStringlist;
 24     function GetIPMsg(IPRecordID: Cardinal): TStringlist;
 25     function GetIPRecordID(IP: string): Cardinal;
 26     function GetIPValue(IP: string): Cardinal;
 27   public
 28     constructor Create(cQQWryFileName: string);
 29     destructor Destroy; override;
 30     function GetLocation(IP: string): String;
 31   end;
 32 
 33 function IPLocation: TIPLocation;
 34 
 35 implementation
 36 
 37 var
 38   __IPLocation: TIPLocation;
 39 
 40 function IPLocation: TIPLocation;
 41 begin
 42   if __IPLocation = nil then
 43     __IPLocation := TIPLocation.Create(ExtractFilePath(ParamStr(0)) +
 44       'qqwry.dat');
 45 
 46   Result := __IPLocation;
 47 end;
 48 
 49 { TIPLocation }
 50 
 51 constructor TIPLocation.Create(cQQWryFileName: string);
 52 begin
 53   inherited Create;
 54   FLock := TCriticalSection.Create;
 55   QQWryFileName := cQQWryFileName;
 56   QQWryFileStream := TBufferedFileStream.Create(QQWryFileName,
 57     fmOpenRead or fmShareDenyWrite, 0);
 58   QQWryFileSize := QQWryFileStream.Size;
 59   QQWryFileStream.Read(FirstIPIndexOffset, 4);
 60   QQWryFileStream.Read(LastIPIndexOffset, 4);
 61   IPRecordNum := (LastIPIndexOffset - FirstIPIndexOffset) div 7 + 1;
 62 end;
 63 
 64 destructor TIPLocation.Destroy;
 65 begin
 66 
 67   QQWryFileStream.Free;
 68   FLock.Free;
 69   inherited Destroy;
 70 end;
 71 
 72 function TIPLocation.GetIPLocation(IPLocationOffset: Cardinal): TStringlist;
 73 const
 74   //                 
 75   REDIRECT_MODE_1 = 1;
 76   REDIRECT_MODE_2 = 2;
 77 var
 78   RedirectMode: byte;
 79   CountryFirstOffset, CountrySecondOffset: Cardinal;
 80   CountryMsg, AreaMsg: string;
 81   //
 82   function ReadString(StringOffset: Cardinal): ansistring;
 83   var
 84     ReadByte: ansichar;
 85   begin
 86     Result := '';
 87     QQWryFileStream.Seek(StringOffset, soFromBeginning);
 88     QQWryFileStream.Read(ReadByte, 1);
 89     while ord(ReadByte) <> 0 do
 90     begin
 91       Result := Result + ReadByte;
 92       QQWryFileStream.Read(ReadByte, 1);
 93     end;
 94   end;
 95 //
 96   function ReadArea(AreaOffset: Cardinal): ansistring;
 97   var
 98     ModeByte: byte;
 99     ReadAreaOffset: Cardinal;
100   begin
101     ReadAreaOffset := 0;
102     QQWryFileStream.Seek(AreaOffset, soFromBeginning);
103     QQWryFileStream.Read(ModeByte, 1);
104     if (ModeByte = REDIRECT_MODE_1) or (ModeByte = REDIRECT_MODE_2) then
105     begin
106       QQWryFileStream.Read(ReadAreaOffset, 3);
107       if ReadAreaOffset = 0 then
108         Result := '    '
109       else
110         Result := ReadString(ReadAreaOffset);
111     end
112     else
113     begin
114       Result := ReadString(AreaOffset);
115     end;
116   end;
117 
118 begin
119   CountryFirstOffset := 0;
120   CountrySecondOffset := 0;
121   //   4   , 4       IP   IP       IP 
122   QQWryFileStream.Seek(IPLocationOffset + 4, soFromBeginning);
123   //              
124   QQWryFileStream.Read(RedirectMode, 1);
125   //      1   
126   if RedirectMode = REDIRECT_MODE_1 then
127   begin
128     //     1,  3                  
129     QQWryFileStream.ReadData(CountryFirstOffset, 3);
130     //      
131     QQWryFileStream.Seek(CountryFirstOffset, soFromBeginning);
132     //                
133     QQWryFileStream.Read(RedirectMode, 1);
134     //            2   
135     if RedirectMode = REDIRECT_MODE_2 then
136     begin
137       //  3                
138       QQWryFileStream.ReadData(CountrySecondOffset, 3);
139       //
140       CountryMsg := ReadString(CountrySecondOffset);
141       //           1,                  2,
142       //                      
143       QQWryFileStream.Seek(CountryFirstOffset + 4, soFromBeginning);
144       //             2   
145     end
146     else
147     begin
148       CountryMsg := ReadString(CountryFirstOffset);
149     end;
150     //       1       
151     AreaMsg := ReadArea(QQWryFileStream.Position);
152     //      2   
153   end
154   else if RedirectMode = REDIRECT_MODE_2 then
155   begin
156     QQWryFileStream.ReadData(CountrySecondOffset, 3);
157     CountryMsg := ReadString(CountrySecondOffset);
158     AreaMsg := ReadArea(IPLocationOffset + 8);
159     //           ,     IP    
160   end
161   else
162   begin
163     CountryMsg := ReadString(QQWryFileStream.Position - 1);
164     AreaMsg := ReadArea(QQWryFileStream.Position);
165   end;
166   Result := TStringlist.Create;
167   Result.Add(CountryMsg);
168   Result.Add(AreaMsg);
169 end;
170 
171 function TIPLocation.GetIPMsg(IPRecordID: Cardinal): TStringlist;
172 var
173   aryStartIP: array [1 .. 4] of byte;
174   strStartIP: string;
175   EndIPOffset: Cardinal;
176   aryEndIP: array [1 .. 4] of byte;
177   strEndIP: string;
178   i: integer;
179 begin
180   EndIPOffset := 0;
181 
182   //     ID           
183   QQWryFileStream.Seek(FirstIPIndexOffset + (IPRecordID - 1) * 7,
184     soFromBeginning);
185   //     4      IP  
186   QQWryFileStream.Read(aryStartIP, 4);
187   //  3            
188   // QQWryFileStream.Read(EndIPOffset, 3);
189   QQWryFileStream.ReadData(EndIPOffset, 3);
190   //       
191   QQWryFileStream.Seek(EndIPOffset, soFromBeginning);
192   //       4      IP  
193   QQWryFileStream.Read(aryEndIP, 4);
194 
195   //    IP          
196   strStartIP := '';
197   for i := 4 downto 1 do
198   begin
199     if i <> 1 then
200       strStartIP := strStartIP + IntToStr(aryStartIP[i]) + '.'
201     else
202       strStartIP := strStartIP + IntToStr(aryStartIP[i]);
203   end;
204   strEndIP := '';
205   for i := 4 downto 1 do
206   begin
207     if i <> 1 then
208       strEndIP := strEndIP + IntToStr(aryEndIP[i]) + '.'
209     else
210       strEndIP := strEndIP + IntToStr(aryEndIP[i]);
211   end;
212   Result := TStringlist.Create;
213   Result.Add(strStartIP);
214   Result.Add(strEndIP);
215   //         IP    
216   //         :①         ②  IP        ③         IP       
217   Result.AddStrings(GetIPLocation(EndIPOffset));
218 end;
219 
220 function TIPLocation.GetIPRecordID(IP: string): Cardinal;
221   function SearchIPRecordID(IPRecordFrom, IPRecordTo, IPValue: Cardinal)
222     : Cardinal;
223   var
224     CompareIPValue1, CompareIPValue2: Cardinal;
225   begin
226     Result := 0;
227     CompareIPValue1 := 0;
228     CompareIPValue2 := 0;
229     QQWryFileStream.Seek(FirstIPIndexOffset + ((IPRecordTo - IPRecordFrom) div 2
230       + IPRecordFrom - 1) * 7, soFromBeginning);
231     QQWryFileStream.Read(CompareIPValue1, 4);
232     QQWryFileStream.Seek(FirstIPIndexOffset + ((IPRecordTo - IPRecordFrom) div 2
233       + IPRecordFrom) * 7, soFromBeginning);
234     QQWryFileStream.Read(CompareIPValue2, 4);
235     //    
236     if (IPValue >= CompareIPValue1) and (IPValue < CompareIPValue2) then
237     begin
238       Result := (IPRecordTo - IPRecordFrom) div 2 + IPRecordFrom;
239     end
240     else
241       //     
242       if IPValue > CompareIPValue1 then
243       begin
244         Result := SearchIPRecordID((IPRecordTo - IPRecordFrom) div 2 +
245           IPRecordFrom + 1, IPRecordTo, IPValue);
246       end
247       else
248         //     
249         if IPValue < CompareIPValue1 then
250         begin
251           Result := SearchIPRecordID(IPRecordFrom, (IPRecordTo - IPRecordFrom)
252             div 2 + IPRecordFrom - 1, IPValue);
253         end;
254   end;
255 
256 begin
257   Result := SearchIPRecordID(1, GetIPRecordNum, GetIPValue(IP));
258 end;
259 
260 function TIPLocation.GetIPRecordNum: Cardinal;
261 begin
262   Result := IPRecordNum;
263 end;
264 
265 function TIPLocation.GetIPValue(IP: string): Cardinal;
266 var
267   tsIP: TStringlist;
268   i: integer;
269   function SplitStringToStringlist(aString: string; aSplitChar: string)
270     : TStringlist;
271   begin
272     Result := TStringlist.Create;
273     while pos(aSplitChar, aString) > 0 do
274     begin
275       Result.Add(copy(aString, 1, pos(aSplitChar, aString) - 1));
276       aString := copy(aString, pos(aSplitChar, aString) + 1,
277         length(aString) - pos(aSplitChar, aString));
278     end;
279     Result.Add(aString);
280   end;
281 
282 begin
283   tsIP := SplitStringToStringlist(IP, '.');
284   Result := 0;
285   for i := 3 downto 0 do
286   begin
287     Result := Result + StrToInt(tsIP[i]) * trunc(power(256, 3 - i));
288   end;
289 end;
290 
291 function TIPLocation.GetLocation(IP: string): String;
292 begin
293   FLock.Enter;
294   try
295     Result := GetIPMsg(GetIPRecordID(IP))[2];
296   finally
297     FLock.Leave;
298   end;
299 end;
300 
301 function TIPLocation.GetQQWryDataFrom: string;
302 begin
303   Result := GetIPMsg(GetIPRecordNum)[2];
304 end;
305 
306 function TIPLocation.GetQQWryDate: TDate;
307 var
308   DateString: string;
309 begin
310   DateString := GetIPMsg(GetIPRecordNum)[3];
311   DateString := copy(DateString, 1, pos('IP  ', DateString) - 1);
312   DateString := StringReplace(DateString, ' ', '-',
313     [rfReplaceAll, rfIgnoreCase]);
314   DateString := StringReplace(DateString, ' ', '-',
315     [rfReplaceAll, rfIgnoreCase]);
316   DateString := StringReplace(DateString, ' ', '-',
317     [rfReplaceAll, rfIgnoreCase]);
318   Result := StrToDate(DateString);
319 end;
320 
321 function TIPLocation.GetQQWryFileName: string;
322 begin
323   Result := QQWryFileName;
324 end;
325 
326 function TIPLocation.GetQQWryFileSize: Cardinal;
327 begin
328   Result := QQWryFileSize;
329 end;
330 
331 initialization
332 
333 finalization
334 
335 if __IPLocation <> nil then
336   __IPLocation.Free;
337 
338 end.

좋은 웹페이지 즐겨찾기