VERSION 1.0 CLASS BEGIN MultiUse = -1 'True Persistable = 0 'NotPersistable DataBindingBehavior = 0 'vbNone DataSourceBehavior = 0 'vbNone MTSTransactionMode = 0 'NotAnMTSObject END Attribute VB_Name = "cInternet" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = True Attribute VB_PredeclaredId = False Attribute VB_Exposed = False Option Explicit ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Objeto responsável por acessar e requisitar dados à Internet ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Guarda o nome do objeto Private Const ST_MY_NAME As String = "cInternet" ' Separador HTTP de endereço Private Const ST_HTTP_INIT_HOST As String = "//" Private Const ST_HTTP_END_HOST As String = "/" Private Const ST_HTTP_PORT_SEP As String = ":" ' Limites de porta Private Const LN_PORT_MIN As Long = 0 Private Const LN_PORT_MAX As Long = 65536 ' Porta padrão Private Const LN_PORT_DEFAULT As Long = 80 ' Separador de pacote HTTP Private Const ST_HTTP_PACKET_SEP As String = ST_LINESEP + ST_LINESEP ' %A Endereço URL ' %H Host ' %K Cookie ' %L Tamanho do pacote POST ' Pacote genérico GET Private Const ST_PACKET_GET As String = "GET %A HTTP/1.0" + ST_LINESEP + _ "Host: %H" + ST_LINESEP + _ "User-Agent: " + ST_LYRIK_USERAGENT + ST_LINESEP + _ "Accept: */*" + ST_LINESEP + _ "Accept-Charset: utf-8" + ST_LINESEP + _ "Accept-Encoding: none" + ST_LINESEP + _ "%K" + _ "%R" + _ "Connection: Close" + ST_HTTP_PACKET_SEP Private Const ST_PACKET_PRX_GET As String = "GET %A HTTP/1.0" + ST_LINESEP + _ "Host: %H" + ST_LINESEP + _ "User-Agent: " + ST_LYRIK_USERAGENT + ST_LINESEP + _ "Accept: */*" + ST_LINESEP + _ "Accept-Charset: utf-8" + ST_LINESEP + _ "Accept-Encoding: none" + ST_LINESEP + _ "%K" + _ "%R" + _ "Proxy-Connection: Close" + ST_HTTP_PACKET_SEP ' Pacote genérico POST Private Const ST_PACKET_POST As String = "POST %A HTTP/1.0" + ST_LINESEP + _ "Host: %H" + ST_LINESEP + _ "User-Agent: " + ST_LYRIK_USERAGENT + ST_LINESEP + _ "Accept: */*" + ST_LINESEP + _ "Accept-Charset: utf-8" + ST_LINESEP + _ "Accept-Encoding: none" + ST_LINESEP + _ "Connection: Close" + ST_LINESEP + _ "%K" + _ "%R" + _ "Content-Type: application/x-www-form-urlencoded" + ST_LINESEP + _ "Content-Length: %L" + ST_HTTP_PACKET_SEP Private Const ST_PACKET_PRX_POST As String = "POST %A HTTP/1.0" + ST_LINESEP + _ "Host: %H" + ST_LINESEP + _ "User-Agent: " + ST_LYRIK_USERAGENT + ST_LINESEP + _ "Accept: */*" + ST_LINESEP + _ "Accept-Charset: utf-8" + ST_LINESEP + _ "Accept-Encoding: none" + ST_LINESEP + _ "Proxy-Connection: Close" + ST_LINESEP + _ "%K" + _ "%R" + _ "Content-Type: application/x-www-form-urlencoded" + ST_LINESEP + _ "Content-Length: %L" + ST_HTTP_PACKET_SEP ' Tradução do pacote Private Const ST_PACKET_ADDRESS As String = "%A" Private Const ST_PACKET_HOST As String = "%H" Private Const ST_PACKET_COOKIE As String = "%K" Private Const ST_PACKET_COOKIE_STR As String = "Cookie: %K" + ST_LINESEP Private Const ST_PACKET_REFERENCE As String = "%R" Private Const ST_PACKET_REFERENCE_STR As String = "Referer: %R" + ST_LINESEP Private Const ST_PACKET_CLENGTH As String = "%L" ' Retorno válido Private Const ST_VALID_RESPONSE As String = "200 OK" ' Evento de resposta Public Event ieEvent(ID As INTERNET_EVENT) ' Guarda a referência de um winsock Private WithEvents ws_Sock As Winsock Attribute ws_Sock.VB_VarHelpID = -1 ' Guarda a referência de um timer (time-out) Private WithEvents tmr_Timer As Timer Attribute tmr_Timer.VB_VarHelpID = -1 ' Guarda dados recebidos do socket Private st_Data As String ' Guarda a ID de requisição Private ln_ID As Long ' Guarda endereço da última requisição Private st_LastAddress As String ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Propriedade do socket ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Property Let Socket(sInput As Winsock) ' Seta Set ws_Sock = sInput End Property Public Property Get Socket() As Winsock ' Retorna Set Socket = ws_Sock End Property ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Propriedade do timer ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Property Let Time(tInput As Timer) ' Seta Set tmr_Timer = tInput End Property Public Property Get Time() As Timer ' Retorna Set Time = tmr_Timer End Property ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Ao iniciar classe ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Class_Initialize() ' Inicia objetos Set ws_Sock = Nothing Set tmr_Timer = Nothing End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Ao fechar classe ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Class_Terminate() On Error Resume Next ' Se tiver timer instanciado If Not (tmr_Timer Is Nothing) Then ' Desativa timer tmr_Timer.Enabled = False End If ' Se tiver instanciado If Not (ws_Sock Is Nothing) Then ' Desconecta o sock ws_Sock.Close End If ' Limpa dados st_Data = ST_INVALID_VALUE ' Libera instâncias Set tmr_Timer = Nothing Set ws_Sock = Nothing End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Pede requisição de uma página ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Sub getPage(stAddress As String, ID As Long, Optional stCookie As String = ST_INVALID_VALUE, Optional blRefresh As Boolean = False, Optional Reference As String = ST_INVALID_VALUE) Dim stAux As String Dim lnAux(1) As Long Dim stHost As String, stHostConn As String Dim lnPort As Long Dim stPage As String Dim stCommand As String On Error GoTo ErrTreat: ' Verifica se está requisitando o último endereço If ((stAddress = st_LastAddress) And (Not blRefresh) And (Len(st_Data) > 0)) Then ' Guarda ID ln_ID = ID ' Informa que dados estão prontos para serem lidos RaiseEvent ieEvent(ieDataArrival) Else ' Encontra o separador inicial de endereço host lnAux(0) = InStr(1, stAddress, ST_HTTP_INIT_HOST) ' Verifica se encontrou If (lnAux(0) > 0) Then ' Seta início real lnAux(0) = lnAux(0) + Len(ST_HTTP_INIT_HOST) ' Encontra o separador final de endereço host lnAux(1) = InStr(lnAux(0), stAddress, ST_HTTP_END_HOST) ' Verifica se encontrou If (lnAux(1) > 0) Then ' Guarda endereço host stHost = Mid(stAddress, lnAux(0), lnAux(1) - lnAux(0)) ' Se usar proxy If bl_ProxyUse Then ' Usa configurações do proxy stHostConn = st_ProxyHost lnPort = ln_ProxyPort ' Seta endereço stPage = stAddress ' Guarda endereço requisitado st_LastAddress = st_ProxyHost + stAddress ' Inicia pacote GET (proxy) stCommand = ST_PACKET_PRX_GET Else ' Seta host de conexão stHostConn = stHost ' Guarda restante do endereço stPage = Mid(stAddress, lnAux(1)) ' Define porta padrão lnPort = LN_PORT_DEFAULT ' Verifica se possui porta específica lnAux(0) = InStr(1, stHost, ST_HTTP_PORT_SEP) If (lnAux(0) > 0) Then ' Guarda a porta em auxiliar stAux = Mid(stHost, lnAux(0) + Len(ST_HTTP_PORT_SEP)) ' Retira a porta do host stHost = Mid(stHost, 1, lnAux(0) - Len(ST_HTTP_PORT_SEP)) ' Verifica se a porta especificada é válida If IsNumeric(stAux) Then If ((CLng(stAux) >= LN_PORT_MIN) And (CLng(stAux) < LN_PORT_MAX)) Then ' Guarda porta lnPort = CLng(stAux) End If End If End If ' Guarda endereço requisitado st_LastAddress = stAddress ' Inicia pacote GET stCommand = ST_PACKET_GET End If ' Se há cookie If (stCookie <> ST_INVALID_VALUE) Then ' Incrementa cookie stCommand = Replace(stCommand, ST_PACKET_COOKIE, ST_PACKET_COOKIE_STR) stCommand = Replace(stCommand, ST_PACKET_COOKIE, stCookie) Else ' Retira cookie stCommand = Replace(stCommand, ST_PACKET_COOKIE, ST_INVALID_VALUE) End If ' Se há referência If (Reference <> ST_INVALID_VALUE) Then ' Incrementa referência stCommand = Replace(stCommand, ST_PACKET_REFERENCE, ST_PACKET_REFERENCE_STR) stCommand = Replace(stCommand, ST_PACKET_REFERENCE, Reference) Else ' Retira referência stCommand = Replace(stCommand, ST_PACKET_REFERENCE, ST_INVALID_VALUE) End If ' Monta pacote GET stCommand = Replace(stCommand, ST_PACKET_ADDRESS, stPage) stCommand = Replace(stCommand, ST_PACKET_HOST, stHost) ' Coloca no buff do sock ws_Sock.Tag = stCommand ' Limpa buff de recepção st_Data = ST_INVALID_VALUE ' Guarda ID ln_ID = ID ' Conecta o socket ws_Sock.Close ws_Sock.Connect stHostConn, lnPort ' Ativa time-out tmr_Timer.Enabled = True ' Sai do procedimento Exit Sub End If End If ' Informa que o endereço é inválido RaiseEvent ieEvent(ieInvalidAddress) End If Exit Sub ErrTreat: LogErrMessage Err.Description, ST_MY_NAME + ".getPage" RaiseEvent ieEvent(ieError) End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Envia dados e recebe um retorno ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Sub postData(stAddress As String, ID As Long, stData As String, Optional stCookie As String = ST_INVALID_VALUE, Optional Reference As String = ST_INVALID_VALUE) Dim stAux As String Dim lnAux(1) As Long Dim stHost As String, stHostConn As String Dim lnPort As Long Dim stPage As String Dim stCommand As String On Error GoTo ErrTreat: ' Encontra o separador inicial de endereço host lnAux(0) = InStr(1, stAddress, ST_HTTP_INIT_HOST) ' Verifica se encontrou If (lnAux(0) > 0) Then ' Seta início real lnAux(0) = lnAux(0) + Len(ST_HTTP_INIT_HOST) ' Encontra o separador final de endereço host lnAux(1) = InStr(lnAux(0), stAddress, ST_HTTP_END_HOST) ' Verifica se encontrou If (lnAux(1) > 0) Then ' Guarda endereço host stHost = Mid(stAddress, lnAux(0), lnAux(1) - lnAux(0)) ' Se usar proxy If bl_ProxyUse Then ' Usa configurações do proxy stHostConn = st_ProxyHost lnPort = ln_ProxyPort ' Seta endereço stPage = stAddress ' Inicia pacote POST (proxy) stCommand = ST_PACKET_PRX_POST Else ' Seta endereço de conexão stHostConn = stHost ' Guarda restante do endereço stPage = Mid(stAddress, lnAux(1)) ' Define porta padrão lnPort = LN_PORT_DEFAULT ' Verifica se possui porta específica lnAux(0) = InStr(1, stHost, ST_HTTP_PORT_SEP) If (lnAux(0) > 0) Then ' Guarda a porta em auxiliar stAux = Mid(stHost, lnAux(0) + Len(ST_HTTP_PORT_SEP)) ' Retira a porta do host stHost = Mid(stHost, 1, lnAux(0) - Len(ST_HTTP_PORT_SEP)) ' Verifica se a porta especificada é válida If IsNumeric(stAux) Then If ((CLng(stAux) >= LN_PORT_MIN) And (CLng(stAux) < LN_PORT_MAX)) Then ' Guarda porta lnPort = CLng(stAux) End If End If End If ' Inicia pacote POST stCommand = ST_PACKET_POST End If ' Guarda endereço requisitado st_LastAddress = ST_INVALID_VALUE ' Se há cookie If (stCookie <> ST_INVALID_VALUE) Then ' Incrementa cookie stCommand = Replace(stCommand, ST_PACKET_COOKIE, ST_PACKET_COOKIE_STR) stCommand = Replace(stCommand, ST_PACKET_COOKIE, stCookie) Else ' Retira cookie stCommand = Replace(stCommand, ST_PACKET_COOKIE, ST_INVALID_VALUE) End If ' Se há referência If (Reference <> ST_INVALID_VALUE) Then ' Incrementa referência stCommand = Replace(stCommand, ST_PACKET_REFERENCE, ST_PACKET_REFERENCE_STR) stCommand = Replace(stCommand, ST_PACKET_REFERENCE, Reference) Else ' Retira referência stCommand = Replace(stCommand, ST_PACKET_REFERENCE, ST_INVALID_VALUE) End If ' Monta pacote POST stCommand = Replace(stCommand, ST_PACKET_ADDRESS, stPage) stCommand = Replace(stCommand, ST_PACKET_HOST, stHost) stCommand = Replace(stCommand, ST_PACKET_CLENGTH, Len(stData)) stCommand = stCommand + stData ' Coloca no buff do sock ws_Sock.Tag = stCommand ' Limpa buff de recepção st_Data = ST_INVALID_VALUE ' Guarda ID ln_ID = ID ' Conecta o socket ws_Sock.Close ws_Sock.Connect stHostConn, lnPort ' Ativa time-out tmr_Timer.Enabled = True ' Sai do procedimento Exit Sub End If End If ' Informa que o endereço é inválido RaiseEvent ieEvent(ieInvalidAddress) Exit Sub ErrTreat: LogErrMessage Err.Description, ST_MY_NAME + ".postData" RaiseEvent ieEvent(ieError) End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Propriedade de leitura dos dados recebidos ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Property Get Data() As String ' Retorna Data = st_Data End Property ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Propriedade de leitura de ID ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Property Get ID() As Long ' Retorna ID = ln_ID End Property ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Ao estourar time-out ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub tmr_Timer_Timer() ' Esvazia buff st_Data = ST_INVALID_VALUE ' Loga erro #If httperr Then LogErrMessage "Connection time-out", ST_MY_NAME + ".tmr_Timer_Timer" #End If ' Força desconexão ws_Sock_Close End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Ao conectar ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub ws_Sock_Connect() On Error GoTo ErrTreat: ' Desativa time-out tmr_Timer.Enabled = False ' Passa os dados de comando ws_Sock.SendData ws_Sock.Tag ' Limpa tag ws_Sock.Tag = ST_INVALID_VALUE ' Ativa time-out tmr_Timer.Enabled = True Exit Sub ErrTreat: LogErrMessage Err.Description, ST_MY_NAME + ".ws_Sock_Connect" RaiseEvent ieEvent(ieError) End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Ao receber dados ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub ws_Sock_DataArrival(ByVal bytesTotal As Long) Dim stBuff As String On Error GoTo ErrTreat: ' Reativa time-out tmr_Timer.Enabled = False tmr_Timer.Enabled = True ' Recebe dados ws_Sock.GetData stBuff ' Concatena st_Data = st_Data + stBuff Exit Sub ErrTreat: LogErrMessage Err.Description, ST_MY_NAME + ".ws_Sock_DataArrival" RaiseEvent ieEvent(ieError) End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Ao terminar conexão ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub ws_Sock_Close() ' Desativa time-out tmr_Timer.Enabled = False ' Fecha socket ws_Sock.Close ' Verifica se conseguiu a resposta desejada If noBuffErr Then ' Tenta separar dados de protocolo If sepPack Then ' Informa que dados estão prontos para serem lidos RaiseEvent ieEvent(ieDataArrival) Exit Sub End If End If ' Limpa buff st_Data = ST_INVALID_VALUE ' Informa erro na requisição RaiseEvent ieEvent(ieInvalidRequest) End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Ocorreu algum erro no objeto winsock ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub ws_Sock_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean) On Error Resume Next ' Desativa time-out tmr_Timer.Enabled = False ' Esvazia buff st_Data = ST_INVALID_VALUE ' Força desconexão ws_Sock_Close End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Retorna se os dados em buff são válidos ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Function noBuffErr() As Boolean Dim lnI As Long On Error GoTo ErrTreat: ' Localiza próxima quebra de linha lnI = InStr(1, st_Data, ST_LINESEP) ' Se localizou If (lnI > 0) Then ' Verifica se na primeira linha possui código válido If InStr(1, Mid(st_Data, 1, lnI), ST_VALID_RESPONSE) Then ' Retorna ok noBuffErr = True ' Sai da função Exit Function Else ' Loga erro #If httperr Then LogErrMessage "HTTP ERROR: " + Mid(st_Data, 1, lnI), ST_MY_NAME + ".noBuffErr" #End If End If Else ' Loga erro #If httperr Then LogErrMessage "HTTP ERROR: " + st_Data, ST_MY_NAME + ".noBuffErr" #End If End If ' Retorna que requisição falhou noBuffErr = False Exit Function ErrTreat: noBuffErr = False End Function ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Separa pacote em dados e protocolo, retorna true se conseguiu ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Function sepPack() As Boolean Dim lnAux As Long On Error GoTo ErrTreat: ' Tenta encontrar o separador nos dados recebidos lnAux = InStr(1, st_Data, ST_HTTP_PACKET_SEP) ' Se encontrou If (lnAux > 0) Then ' Separa dados st_Data = Mid(st_Data, lnAux + Len(ST_HTTP_PACKET_SEP)) ' Informa que conseguiu separar sepPack = True Else ' Informa que não conseguiu separar, pacote possivelmente corrompido sepPack = False End If Exit Function ErrTreat: sepPack = False End Function ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Progresso de envio ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub ws_Sock_SendProgress(ByVal bytesSent As Long, ByVal bytesRemaining As Long) ' Desativa time-out tmr_Timer.Enabled = False ' Se ainda tiver dados para serem enviados If (bytesRemaining > 0) Then ' Ativa time-out tmr_Timer.Enabled = True End If End Sub