Этюды на 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'а:
<SITEMAP> <MVC> <ASP> <NET> <DATA> <KIOSK> <FLEX> <SQL> <NOTES> <LINUX> <MONO> <FREEWARE> <DOCS> <ENG> <CHAT ME> <ABOUT ME> < THANKS ME> |