(ASP.NET) ASP.NET (2009 год)

Этюды на ASP2. Обращение к Whois-сервису.


Однажды в своих поисках по Sourceforge.net я случайно наткнулся на чудо-прогу Whois. Удивило и заинтересовало, что код этой чудо-проги секретный - несмотря на выкладку проекта на SourceForge. Прочие ацкие проги на эту же тему на SourceForge меня удивили еще больше. Я заинтересовался этим вопросом и обратил внимание, что даже одна из самых популярных прог микрософтовского небожителя Mark'а Russinovich'а также является та же самая прога, только еще в более убогом консольном варианте и с кучей предупреждений о необходимости соблюдать лицензионные соглашения с империей Билла Гейтса.

Я решил "показать все что скрыто" в этой микрософтовской чудо-проге и всех прочих подобных чудо-сервисах. Ниже вы можете увидеть, что скрывают Марик и гавнасофт - а там есть что скрывать - это семь строк на бейсике 26,27,28,34,35,36,44 и плюс пару страндартных строк общей обвязки, чтобы все это работало на асповской страничке.

  0001:  Partial Class Whois
  0002:      Inherits System.Web.UI.Page
  0003:   
  0004:      Protected Sub Whois_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  0005:          If Not IsPostBack Then
  0006:              If Not HttpContext.Current.User.Identity.IsAuthenticated Then
  0007:                  Response.Redirect("Login.aspx")
  0008:              End If
  0009:          End If
  0010:      End Sub
  0011:   
  0012:      Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
  0013:          Label1.Text = MyWhois_Go(TextBox1.Text, "whois.ripn.net")
  0014:      End Sub
  0015:   
  0016:      Public Shared Function MyWhois_Go(ByVal SearchHost As String, ByVal WhoisServer As String) As String
  0017:          Dim WhoisPort As Integer = 43
  0018:          Dim TcpSocket As System.Net.Sockets.TcpClient
  0019:          Dim networkStream As System.Net.Sockets.NetworkStream
  0020:          Dim baseStream As System.IO.BufferedStream
  0021:          Dim inputStream As System.IO.StreamReader
  0022:          Dim outputStream As System.IO.StreamWriter
  0023:          Dim OutString As New Text.StringBuilder
  0024:          'коннектимся
  0025:          Try
  0026:              TcpSocket = New System.Net.Sockets.TcpClient(WhoisServer, WhoisPort)
  0027:              networkStream = TcpSocket.GetStream()
  0028:              baseStream = New System.IO.BufferedStream(networkStream)
  0029:          Catch se As System.Net.Sockets.SocketException
  0030:              Return "Нет коннекта" & vbCrLf & se.Message
  0031:          End Try
  0032:          'отправили запрос
  0033:          Try
  0034:              outputStream = New System.IO.StreamWriter(baseStream)
  0035:              outputStream.WriteLine(SearchHost)
  0036:              outputStream.Flush()
  0037:          Catch e As Exception
  0038:              Return "Не принят запрос" & vbCrLf & e.Message
  0039:          End Try
  0040:          ' ждем ответ
  0041:          Try
  0042:              inputStream = New System.IO.StreamReader(baseStream)
  0043:              While Not inputStream.EndOfStream
  0044:                  Dim Tmp1 As String = inputStream.ReadLine()
  0045:                  If (Not Tmp1.StartsWith("%")) And (Not Tmp1 = "") Then
  0046:                      OutString.AppendLine(Tmp1 & "<br>")
  0047:                  End If
  0048:              End While
  0049:          Catch e As Exception
  0050:              Return "Нет ответа" & vbCrLf & e.Message
  0051:          End Try
  0052:          'все, прочитали до конца
  0053:          TcpSocket.Close()
  0054:          Return OutString.ToString
  0055:      End Function
  0056:   
  0057:  End Class

В реальности эта прога вызывается конечно в цикле для заполнения базы. Потом можно отдавать пользователю ответ уже из своей базы, а не загружать Whois-сервис рунета. Который к тому же блокирует слишком назойливых клиентов.

Поэтому во всех циклах обращения к Whois-сервису должна присутсвовать волшебная строчка:

  0000:  System.Threading.Thread.Sleep(3000) '3000 - три секунды ждем (30 раз в минуту - блокировка)



Для тех, кого интересует практическая часть - я также покажу простейший прямолинейный код парсера Whois-ответа, которым сформирована база на скрине выше.


  0001:      ''' <summary>
  0002:      ''' Прасинг Whois-ответа
  0003:      ''' </summary>
  0004:      Sub WhoisParsed(ByVal Html As String, ByVal WriteCMD As SqlClient.SqlCommand)
  0005:          Dim L As Integer = Len(Html)
  0006:          Dim Pos1(20) As Integer
  0007:          Dim Email1 As String = " "
  0008:          Dim Email2 As String = " "
  0009:          Dim DNS1 As String = " "
  0010:          Dim DNS2 As String = " "
  0011:          Dim Person As String = " "
  0012:          Dim Orgainsation As String = " "
  0013:          Dim Created As String = " "
  0014:          Pos1(1) = Html.IndexOf("nserver:")
  0015:          If Pos1(1) > 0 Then
  0016:              Pos1(2) = Html.IndexOf("<br>", Pos1(1))
  0017:              If Pos1(2) > 0 Then
  0018:                  DNS1 = Html.Substring(Pos1(1) + Len("nserver:"), Pos1(2) - Pos1(1) - Len("nserver:")).Trim
  0019:                  Pos1(20) = Pos1(2) + 1
  0020:              End If
  0021:          Else
  0022:              Pos1(20) = Pos1(1) + 1
  0023:              
  0024:          End If
  0025:          If Pos1(20) >= L - 1 Then GoTo Write
  0026:          '
  0027:          Pos1(3) = Html.IndexOf("nserver:", Pos1(20))
  0028:          If Pos1(3) > 0 Then
  0029:              Pos1(4) = Html.IndexOf("<br>", Pos1(3))
  0030:              If Pos1(4) > 0 Then
  0031:                  DNS2 = Html.Substring(Pos1(3) + Len("nserver:"), Pos1(4) - Pos1(3) - Len("nserver:")).Trim
  0032:                  Pos1(20) = Pos1(4) + 1
  0033:              End If
  0034:          Else
  0035:              Pos1(20) = Pos1(3) + 1
  0036:          End If
  0037:          If Pos1(20) >= L - 1 Then GoTo Write
  0038:          '
  0039:          Pos1(5) = Html.IndexOf("org:", Pos1(20))
  0040:          If Pos1(5) > 0 Then
  0041:              Pos1(6) = Html.IndexOf("<br>", Pos1(5))
  0042:              If Pos1(6) > 0 Then
  0043:                  Orgainsation = Html.Substring(Pos1(5) + Len("org:"), Pos1(6) - Pos1(5) - Len("org:")).Trim
  0044:                  Pos1(20) = Pos1(6) + 1
  0045:              End If
  0046:          Else
  0047:              Pos1(20) = Pos1(5) + 1
  0048:          End If
  0049:          If Pos1(20) >= L - 1 Then GoTo Write
  0050:          '
  0051:          Pos1(7) = Html.IndexOf("person:", Pos1(7))
  0052:          If Pos1(7) > 0 Then
  0053:              Pos1(8) = Html.IndexOf("<br>", Pos1(7))
  0054:              If Pos1(8) > 0 Then
  0055:                  Person = Html.Substring(Pos1(7) + Len("person:"), Pos1(8) - Pos1(7) - Len("person:")).Trim
  0056:                  Pos1(20) = Pos1(8) + 1
  0057:              End If
  0058:          Else
  0059:              Pos1(20) = Pos1(7) + 1
  0060:          End If
  0061:          If Pos1(20) >= L - 1 Then GoTo Write
  0062:          '
  0063:          Pos1(9) = Html.IndexOf("e-mail:", Pos1(20))
  0064:          If Pos1(9) > 0 Then
  0065:              Pos1(10) = Html.IndexOf("<br>", Pos1(9))
  0066:              If Pos1(10) > 0 Then
  0067:                  Email1 = Html.Substring(Pos1(9) + Len("e-mail:"), Pos1(10) - Pos1(9) - Len("e-mail:")).Trim
  0068:                  Pos1(20) = Pos1(10) + 1
  0069:              End If
  0070:          Else
  0071:              Pos1(20) = Pos1(9) + 1
  0072:          End If
  0073:          If Pos1(20) >= L - 1 Then GoTo Write
  0074:          '
  0075:          Pos1(11) = Html.IndexOf("e-mail:", Pos1(20))
  0076:          If Pos1(11) > 0 Then
  0077:              Pos1(12) = Html.IndexOf("<br>", Pos1(11))
  0078:              If Pos1(12) > 0 Then
  0079:                  Email2 = Html.Substring(Pos1(11) + Len("e-mail:"), Pos1(12) - Pos1(11) - Len("e-mail:")).Trim
  0080:                  Pos1(20) = Pos1(12) + 1
  0081:              End If
  0082:          Else
  0083:              Pos1(20) = Pos1(11) + 1
  0084:          End If
  0085:          If Pos1(20) >= L - 1 Then GoTo Write
  0086:          '
  0087:          Pos1(13) = Html.IndexOf("created:", Pos1(20))
  0088:          If Pos1(13) > 0 Then
  0089:              Pos1(14) = Html.IndexOf("<br>", Pos1(13))
  0090:              If Pos1(14) > 0 Then
  0091:                  Created = Html.Substring(Pos1(13) + Len("created:"), Pos1(14) - Pos1(13) - Len("created:")).Trim
  0092:                  Pos1(20) = Pos1(14) + 1
  0093:              End If
  0094:          Else
  0095:              Pos1(20) = Pos1(13) + 1
  0096:          End If
  0097:          If Pos1(20) >= L - 1 Then GoTo Write
  0098:  write:
  0099:          WriteCMD.Parameters("Email1").Value = Email1
  0100:          WriteCMD.Parameters("Email2").Value = Email2
  0101:          WriteCMD.Parameters("DNS1").Value = DNS1
  0102:          WriteCMD.Parameters("DNS2").Value = DNS2
  0103:          WriteCMD.Parameters("Person").Value = Person
  0104:          WriteCMD.Parameters("Orgainsation").Value = Orgainsation
  0105:          WriteCMD.Parameters("Created").Value = Created
  0106:          WriteCMD.ExecuteNonQuery()
  0107:   
  0108:      End Sub

И еще один небольшой практический совет. Многие каталоги имеют странный баг - который я не могу обьяснить. Его вы видите слева. Возможно, URL набивается вручную и это просто опечатка, возможно это баг проги, формирующей известные каталоги сайтов.

Но ублюдочный микрософтовский парсер

Dim URI As New Uri(DR1("URL"))
на этом баге падает. Конечно его можно обложить скобками TRY - но ведь от этого он не распарсит правильно доменное имя, которое надо скормить Whois-сервису?

Поэтому на практике эти тупые микрософтовские примочки использовать не рекомендуется. Я выковыриваю доменное имя из URL следующим простейшим кодом, устойчивым к этому багу (и другим распространенным багам верстальщиц, когда они например пропускают закрывающую кавычку).

Поддомены этот код не отделяет (в моем поисковике это делается на более ранних этапах). Чтобы его отделять здесь - добавьте еще строчку: если встретили более одной точки в переменной Domain - ставьте в базе флаг, что это поддомен.



   0001:   
   0002:      ''' <summary>
   0003:      ''' Парсинг страничек в поисках ссылок заданных как http:// (поддомены тут не отделяются)
   0004:      ''' </summary>
   0005:      Sub URLSearch(ByVal Html As String, ByVal WriteCMD As SqlClient.SqlCommand)
   0006:          Dim L As Integer = Len(Html)
   0007:          Dim Pos1 As Integer
   0008:          Dim Len1 As Integer = Len("http://")
   0009:          Dim Pos2, Pos3, Pos4, Pos5, Pos6, Pos7, Pos8, PosR As Integer
   0010:          Dim URL As String
   0011:          While Pos1 < L And PosR < L
   0012:              Pos1 = Html.IndexOf("http://", PosR)
   0013:              If Pos1 > 0 Then
   0014:                  Pos2 = Html.IndexOf("""", Pos1)
   0015:                  Pos3 = Html.IndexOf("'", Pos1)
   0016:                  Pos4 = Html.IndexOf(",", Pos1)
   0017:                  Pos5 = Html.IndexOf("?", Pos1)
   0018:                  Pos6 = Html.IndexOf(" ", Pos1)
   0019:                  Pos7 = Html.IndexOf(">", Pos1)
   0020:                  Pos8 = Html.IndexOf("<", Pos1)
   0021:                  PosR = Math.Min(Math.Min(Math.Min(Math.Min(Math.Min(Pos2, Pos3), Pos5), Pos6), Pos7), Pos8)
   0022:                  If PosR > 0 Then
   0023:                      URL = Html.Substring(Pos1, PosR - Pos1).Replace("""", "").Replace("'", "").Replace("?", "").Replace(">", "").Replace("<", "").Trim
   0024:                      Dim Domain As String = URL.ToString.Replace("http://", "").Replace("www.", "").Replace(",", ".").Trim
   0025:                      Dim PosD As Integer = Domain.IndexOf("/")
   0026:                      If PosD > 0 Then Domain = Domain.Substring(0, PosD)
   0027:                      If Domain.Length < 50 And Domain <> "" And URL <> "" Then
   0028:                          WriteCMD.Parameters("URL").Value = URL
   0029:                          WriteCMD.Parameters("Domain").Value = Domain.ToLower
   0030:                          WriteCMD.ExecuteNonQuery()
   0031:                      End If
   0032:                      Pos1 = PosR
   0033:                  Else
   0034:                      Exit While
   0035:                  End If
   0036:              Else
   0037:                  Exit While
   0038:              End If
   0039:          End While
   0040:      End Sub

Итак, я показал вам здесь OpenSource семь волшебных строчек онлайнового обращения к Whois-server'у, строку ожидания в цикле обращения к Whois-сервису рунета для формирования собственной базы, правильную технику формирования доменного имени для Whois-запроса и простейший линейно-строчный парсер ответа Whois-сервера.

Открытый здесь фрагмент кода является одним из важнейших компонентов одной из моих популярных программ WebDownloader'а:







Комментарии к этой страничке ( )
ссылка на эту страничку: http://www.vb-net.ru/asp2/45/index.htm
<На главную>  <В раздел ASP>  <В раздел NET>  <В раздел SQL>  <В раздел Разное>  <Написать автору>  < Поблагодарить>
Московская хельсинская группа   Радио Свобода  Новая газета   The New Times (Новое время)    Rambler's Top100