Enviando mensajes de WhatsApp

Re: Enviando mensajes de WhatsApp

Postby lucasdebeltran » Fri Aug 17, 2012 5:24 pm

Antonio,

Muchas gracias.

Y cuando el teléfono ya está previamente registrado, ¿no es posible averiguar la contraseña en uso?.

¿Qué teléfono tienes tú Antonio?.

Muchas gracias.
Muchas gracias. Many thanks.

Un saludo, Best regards,

Harbour 3.2.0dev, Borland C++ 5.82 y FWH 13.06 [producción]

Implementando MSVC 2010, FWH64 y ADO.

Abandonando uso xHarbour y SQLRDD.
User avatar
lucasdebeltran
 
Posts: 1303
Joined: Tue Jul 21, 2009 8:12 am

Re: Enviando mensajes de WhatsApp

Postby Antonio Linares » Fri Aug 17, 2012 5:49 pm

Lucas,

No, la contraseña no es publica. La usa WhatsApp internamente, Solo se sabe, hasta ahora, como se genera en Android.

Yo estaba probando con un WhatsApp en un iphone y por eso no me funcionaba. Hoy he probado con Android y ya me funciona :-)

De todas formas vamos a portar el código para poder cambiar la contraseña segun se explica aqui:
http://lukasklein.com/blog/custom-ios-whatsapp-password/
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41394
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Enviando mensajes de WhatsApp

Postby Antonio Linares » Fri Aug 17, 2012 5:51 pm

Versión más reciente:

A mi no me funciona aún el RequestLastSeen() y a vosotros ?

Code: Select all  Expand view
#include "FiveWin.ch"
#include "hbsocket.ch"

function Main()
                                                                   
   local oWA := HB_WhatsApp():New( "34684078311", hb_md5( StrRev( "mi IMEI" ) ), "nickname" )

   oWA:Connect()
   oWA:Login()

   ? oWA:cAccount_status, oWA:cAccount_kind, oWA:cAccount_creation, oWA:cAccount_expiration
   
   oWA:RequestLastSeen( "34670463032" )
   
   oWA:Message( Str( TS2Num() ), "34670463032", "Testing" )

return nil

CLASS HB_WhatsApp

   DATA  cAccount_status, cAccount_kind, cAccount_creation, cAccount_expiration
   DATA  cNumber, cPassword, cNickname
   DATA  pSocket
   DATA  cServer INIT "s.whatsapp.net"
   DATA  cHost   INIT "bin-short.whatsapp.net"
   DATA  cRealm  INIT "s.whatsapp.net"
   DATA  nPort   INIT 5222
   DATA  cIP
   DATA  cQop    INIT "auth"
   DATA  cDigest_Uri INIT "xmpp/s.whatsapp.net"
   DATA  aResArray
   DATA  cMsg
   DATA  _Incomplete_message
   DATA  LastSeen

   METHOD New( cNumber, cPassword, cNickname )
   METHOD Connect()
   METHOD Login()
   METHOD Message( cMmsgid, cTo, cTxt )
   METHOD Read()
   METHOD Send( cData )
   METHOD parse_last_seen( cMsg )
   METHOD parse_received_message( cMsg )
   METHOD RequestLastSeen( mobile )

   METHOD _Authenticate( cNonce, cNC )
   METHOD _Identify( cStr )
   METHOD _Is_Full_Msg( cStr )
   METHOD parse_account_info( msg )

   DESTRUCTOR Destroy()

ENDCLASS

METHOD New( cNumber, cPassword, cNickname ) CLASS HB_WhatsApp

   ::cIP = hb_socketGetHosts( ::cHost )[ 1 ]
   ::pSocket = hb_socketOpen()

   ::cNumber   = cNumber
   ::cPassword = cPassword
   ::cNickname = cNickname

return self

METHOD Connect() CLASS HB_WhatsApp

return hb_socketConnect( ::pSocket, { HB_SOCKET_AF_INET, ::cIP, ::nPort } )

static function StrToHex( cStr )

   local n, cHex := ""
   
   for n = 1 to Len( cStr )
      cHex += "0x" + PadL( hb_NumToHex( Asc( SubStr( cStr, n, 1 ) ) ), "0", 2 )
      if n < Len( cStr )
         cHex += ", "
      endif  
   next
   
return cHex        

static function random_uuid()

return hb_strformat( "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",;
                     hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ),;
                     hb_Random( 0, 0xffff ),;
                     hb_BitOr( hb_Random( 0, 0x0fff ), 0x4000 ),;
                     hb_BitOr( hb_Random( 0, 0x3fff ), 0x8000 ),;
                     hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ) )
             
METHOD Login() CLASS HB_WhatsApp

   local cBuffer, cResponse, aArrResponse, hAuthData, cValue, aResData, cResData

   ::Send( "WA" + Chr( 0x01 ) + Chr( 0 ) + Chr( 0 ) + ;
             Chr( 0x19 ) + Chr( 0xF8 ) + Chr( 0x05 ) + Chr( 0x01 ) + ;
             Chr( 0xA0 ) + Chr( 0x8A ) + Chr( 0x84 ) + Chr( 0xFC ) + ;
             Chr( 0x11 ) + "iPhone-2.6.9-5222" + ;
             Chr( 0 ) + Chr( 0x08 ) + Chr( 0xF8 ) + Chr( 0x02 ) + ;
             Chr( 0x96 ) + Chr( 0xF8 ) + Chr( 0x01 ) + Chr( 0xF8 ) + ;
             Chr( 0x01 ) + Chr( 0x7E ) + Chr( 0 ) + Chr( 0x07 ) + Chr( 0xF8 ) + ;
             Chr( 0x05 ) + Chr( 0x0F ) + Chr( 0x5A ) + Chr( 0x2A ) + ;
             Chr( 0xBD ) + Chr( 0xA7 ) )

   cBuffer = ::Read()
   cResponse = hb_base64decode( SubStr( cBuffer, 27 ) )
   aArrResponse = HB_ATokens( cResponse, "," )
   hAuthData = {=>}
   
   for each cValue in aArrResponse
      aResData = hb_ATokens( cValue, "=" )
      hAuthData[ aResData[ 1 ] ] = StrTran( aResData[ 2 ], '"', "" )
   next    
   
   cResData = ::_Authenticate( hAuthData[ "nonce" ] )
   cResponse = Chr( 0x01 ) + Chr( 0x31 ) + Chr( 0xF8 ) + Chr( 0x04 ) + Chr( 0x86 ) + ;
               Chr( 0xBD ) + Chr( 0xA7 ) + Chr( 0xFD ) + Chr( 0 ) + Chr( 1 ) + Chr( 0x28 ) + ;
               hb_base64encode( cResData )
   ::Send( cResponse )
   cBuffer = ::Read()
   ::Read()
   cResponse = Chr( 0 ) + Chr( 8 + Len( ::cNickname ) ) + Chr( 0xF8 ) + Chr( 5 ) + Chr( 0x74 ) + ;
               Chr( 0xA2 ) + Chr( 0xA3 ) + Chr( 0x61 ) + Chr( 0xFC ) + Chr( Len( ::cNickName ) ) + ;
               ::cNickName + Chr( 0 ) + Chr( 0x15 ) + Chr( 0xF8 ) + Chr( 6 ) + Chr( 0x48 ) + ;
               Chr( 0x43 ) + Chr( 5 ) + Chr( 0xA2 ) + Chr( 0x3A ) + Chr( 0xF8 ) + Chr( 1 ) + ;
               Chr( 0xF8 ) + Chr( 4 ) + Chr( 0x7B ) + Chr( 0xBD ) + Chr( 0x4D ) + Chr( 0xF8 ) + ;
               Chr( 1 ) + Chr( 0xF8 ) + Chr( 3 ) + Chr( 0x55 ) + Chr( 0x61 ) + Chr( 0x24 ) + ;
               Chr( 0 ) + Chr( 0x12 ) + Chr( 0xF8 ) + Chr( 8 ) + Chr( 0x48 ) + Chr( 0x43 ) + ;
               Chr( 0xFC ) + Chr( 1 ) + Chr( 0x32 ) + Chr( 0xA2 ) + Chr( 0x3A ) + Chr( 0xA0 ) + ;
               Chr( 0x8A ) + Chr( 0xF8 ) + Chr( 1 ) + Chr( 0xF8 ) + Chr( 3 ) + Chr( 0x1F ) + ;
               Chr( 0xBD ) + Chr( 0xB1 )
   ::Send( cResponse )
   ::Read()    
   
return nil

METHOD _Authenticate( cNonce, cNC ) CLASS HB_WhatsApp

   local cCNonce := random_uuid()
   local cA1 := hb_StrFormat( "%s:%s:%s", ::cNumber, ::cServer, ::cPassword )
   local cA2, cPassword

   if cNC == nil
      cNC = "00000001"
   endif
   
   cA1 = pack_h32( hb_md5( cA1 ) ) + ":" + cNonce + ":" + cCNonce  
   cA2 = "AUTHENTICATE:" + ::cDigest_Uri
   cPassword = hb_md5( cA1 ) + ":" + cNonce + ":" + cNC + ":" + cCNonce + ":" + ::cQop + ;
               ":" + hb_md5( cA2 )
   cPassword = hb_md5( cPassword )            
   
return hb_StrFormat( 'username="%s",realm="%s",nonce="%s",cnonce="%s",nc=%s,qop=%s,digest-uri="%s",response=%s,charset=utf-8',;
                     ::cNumber, ::cRealm, cNonce, cCnonce, cNC, ::cQop, ::cDigest_Uri, cPassword )  
 
METHOD Message( cMsgid, cTo, cTxt ) CLASS HB_WhatsApp

   local lLong_txt_bool := isShort( cTxt )
   local cStream , cMsg, cContent, cTxt_length
   local cTo_length
   local cMsgid_length
   local cTotal_length
   
   cTo_length = Chr( Len( cTo ) )
   cMsgid_length = Chr( Len( cMsgid ) )
   cTxt_length = Chr( Len( cTxt ) )
   
   cContent = Chr( 0xF8 ) + Chr( 0x08 ) + Chr( 0x5D ) + Chr( 0xA0 ) + Chr( 0xFA ) + Chr( 0xFC ) + cTo_length
   cContent += cTo
   cContent += Chr( 0x8A ) + Chr( 0xA2 ) + Chr( 0x1B ) + Chr( 0x43 ) + Chr( 0xFC ) + cMsgid_length
   cContent += cMsgid
   cContent += Chr( 0xF8 ) + Chr( 0x02 ) + Chr( 0xF8 ) + Chr( 0x04 ) + Chr( 0xBA ) + Chr( 0xBD ) + Chr( 0x4F) + ;
               Chr( 0xF8 ) + Chr( 0x01 ) + Chr( 0xF8 ) + Chr( 0x01 ) + Chr( 0x8C ) + Chr( 0xF8 ) + Chr( 0x02 ) + Chr( 0x16 )

   if ! lLong_txt_bool
      cContent += Chr( 0xFD ) + Chr( 0 ) + cTxt_length
   else
      cContent += Chr( 0xFC ) + cTxt_length
   endif
 
   cContent += cTxt
 
   cTotal_length = Chr( Len( cContent ) )
   
   if Len( cTotal_length ) == 1
      cTotal_length = Chr( 0 ) + cTotal_length
   endif
   
   cMsg := cTotal_length + cContent
   
   cStream := ::Send( cMsg )
   ::Read()
   // ::Read()
   // ::Read()
       
Return nil
 
METHOD parse_received_message( cMsg ) CLASS HB_WhatsApp

   local message := { => }, nLength

   // RCVD MSG IN STRING
   nLength = Asc( SubStr( cMsg, 1, 1 ) )
   message[ 'length' ] = nLength  // PACKET EXCLUDING 00 AND FIRST HEX SHOULD EQUAL THIS NUMBER
   
   cMsg = SubStr( cMsg, 3 )       // Remove Length & F8
   message[ 'sec_length' ] = Asc( SubStr( cMsg, 1, 1 ) )       // Length of something i dont know excatly what  
   cMsg = SubStr( cMsg, 6 )       // Remove Second Length ( 1 HEX ) , Remove XML Chrs ( 4 HEX )
   message[ 'from_number_length' ] = Asc( SubStr( cMsg, 1, 1 ) )
   
   cMsg = SubStr( cMsg, 2 )       // Remove Length
   message[ 'from_number' ] = SubStr( cMsg, 1, message[ 'from_number_length' ] )
   
   cMsg = SubStr( cMsg, message[ 'from_number_length' ] + 1 )             // Remove NUMBER
   cMsg = SubStr( cMsg,4 )       // Remove F8 & XML ( 2 HEX )
   message[ 'message_id_length' ] = Asc( SubStr( cMsg, 1, 1 ) )
   cMsg = Substr( cMsg, 2 )       // Remove Length
   message[ 'message_id' ] = SubStr( cMsg, 1, message[ 'message_id_length' ] )
   cMsg = SubStr( cMsg, message[ 'message_id_length' ] + 1 )
   cMsg = SubStr( cMsg, 5 )       // Remove XML ( 4 HEX )
   message[ 'timestamp_length' ] = Asc( SubStr( cMsg, 1, 1 ) )
   cMsg = SubStr( cMsg, 2 )       // Remove Length
   message[ 'timestamp' ] = Num2TS( Val( SubStr( cMsg, 1, message[ 'timestamp_length' ] ) ) )
   
   cmsg = SubStr( cMsg, message[ 'timestamp_length' ] + 1 )               // Remove Timestamp
   // Check for Retry header
   if Substr( cMsg, 1, 1 ) == Chr( 0x88 )
      cMsg = SubStr( cMsg, 5 )       // Remove Retry Length , i dont think i will need it
   endif
   
   cmsg = Substr( cMsg, 10 )      // Remove XMPP XML and Name XML Headers
   message[ 'sender_name_length' ] = Asc( SubStr( cMsg, 1, 1 ) )
   cmsg = SubStr( cMsg, 2 )       // Remove Length
   message[ 'sender_name' ] = SubStr( cMsg, 1, message[ 'sender_name_length' ] )
   
   cMsg = SubStr( cMsg, message[ 'sender_name_length' ] + 1 )   // Remove sender from msg
   cMsg = SubStr( cMsg, 10 )      // Remove body headers
   message[ 'body_txt_length' ] = Asc( SubStr( cMsg, 1, 1 ) )

   cMsg = SubStr( cMsg, 2 )       // Remove Length
   message[ 'body_txt' ] = SubStr( cMsg, 1, message[ 'body_txt_length' ] )

   cMsg = SubStr( cMsg, message[ 'body_txt_length' ] + 1 )  // Remove body txt
   cMsg = SubStr( cMsg, 10 )      // Remove XMPP XML and Name XML Headers
   message[ 'time_length' ] = Asc( SubStr( cMsg, 1, 1 ) )

   cMsg = SubStr( cMsg, 2 )       // Remove Length
   message[ 'time' ] = SubStr( cMsg, 1, message[ 'time_length' ] )        
   cMsg = SubStr( cMsg, message[ 'time_length' ] + 1 )

   ? "From: " + message[ 'sender_name' ] + CRLF + ;
     "msg:  " + message[ 'body_txt' ] + CRLF + ;
     "date: " + message[ 'timestamp' ]
   
return message
               
METHOD Read() CLASS HB_WhatsApp

   local cBuffer := Space( 1024 ), cV, cRcvdType
   local nLen := hb_socketRecv( ::pSocket, @cBuffer )

   cBuffer = SubStr( cBuffer, 1, nLen )
   ::aResArray = HB_ATokens( cBuffer, Chr( 0 ) )
   // ? StrToHex( cBuffer )
   
   for each cV in ::aResArray
      cRcvdType = ::_Identify( cV )

      // ? cRcvdType
      // ? StrToHex( cV )

      do case
         case cRcvdType == "incomplete_msg"
              ::_incomplete_message = cV

         case cRcvdType == "msg"
              ::cMsg = ::parse_received_message( cV )
         
         case cRcvdType == "account_info"
              ::parse_account_info( cV )

         case cRcvdType == "last_seen"
              ::lastseen = ::parse_last_seen( cV )
      endcase
   next

return cBuffer
   
METHOD parse_account_info( cMsg )

   local nAcst, nActkind
   local x := { => }
   local nCreation_timstamp_len, nExpr_length
   
    cMsg = SubStr( cMsg, 4 )        // Remove Length,F8,second length
    cMsg = SubStr( cMsg, 5 )        // Remove Success XML
    // Next should be status
    nAcst = Asc( SubStr( cMsg, 1, 1 ) )
    if nAcst == 0x09
       ::cAccount_status = 'active'
    else
       ::cAccount_status = 'inactive'
    endif
    cMsg = SubStr( cMsg, 3 )        // Remove status & KIND XML
    nActkind = Asc( SubStr( cMsg, 1, 1 ) )
    if nActkind == 0x37
       ::cAccount_kind = 'free'
    else
       ::cAccount_kind = 'paid'
    endif
    cMsg = SubStr( cMsg, 4 )        // Remove XML
    nCreation_timstamp_len = Asc( SubStr( cMsg, 1, 1 ) ) // Should return 10 for the next few thousdands years
    cMsg = SubStr( cMsg, 2 )        // Remove Length
    ::cAccount_creation := Num2TS( Val( SubStr( cMsg, 1, nCreation_timstamp_len ) ) )
    cMsg = SubStr( cMsg, nCreation_timstamp_len + 1 )       // Remove Timestamp
    cMsg = SubStr( cMsg, 3 )        // Remove Expiration XML
    nExpr_length = Asc( SubStr( cMsg, 1, 1 ) ) // Should also be 10
    cMsg = SubStr( cMsg, 2 )        // Remove Length
    ::cAccount_expiration := Num2TS( Val( SubStr( cMsg, 1, nExpr_length ) ) )

return nil

METHOD RequestLastSeen( mobile ) CLASS HB_WhatsApp

   local mob_len, content, len, total_length, request, stream

   mob_len = Chr( Len( mobile ) )
   content = Chr( 0xF8 ) + Chr( 0x08 ) + Chr( 0x48 ) + Chr( 0x43 ) + Chr( 0xFC )
   content += Chr( 0x01 ) + Chr( 0x37 ) + Chr( 0xA2 ) + Chr( 0x3A ) + Chr( 0xA0 )
   content += Chr( 0xFA ) + Chr( 0xFC ) + mob_len
   content += mobile
   content += Chr( 0x8A ) + Chr( 0xF8 ) + Chr( 0x01 ) + Chr( 0xF8 ) + Chr( 0x03 )
   content += Chr( 0x7B ) + Chr( 0xBD ) + Chr( 0x4C )

   len = Len( content )
   total_length = Chr( len )

   request = Chr( 0 )
   request += total_length
   request += content
   stream  = ::Send( request )
   ::Read()
   ::Read()

return nil

METHOD parse_last_seen( cMsg ) CLASS HB_WhatsApp

   Local lastseen := {=>}, moblen, last_seen_len

   cMsg = SubStr( cMsg, 8 )  // Remove Some XML DATA
   moblen= Asc( SubStr( cMsg, 1, 1 ) )
   cMsg = SubStr( cMsg, 2 )  // Remove Length
   lastseen[ 'mobile' ] = SubStr( cMsg, 1, moblen )
   cMsg = SubStr( cMsg, moblen + 1 )
   cMsg = SubStr( cMsg, 17 ) // Remove Some More XML DATA
   last_seen_len = Asc( SubStr( cMsg, 1, 1 ) )
   cmsg = SubStr( cMsg, 2 )  // Remove Length
   lastseen[ 'seconds_ago' ] = SubStr( cMsg, 0, last_seen_len )

return lastseen

METHOD Send( cData ) CLASS HB_WhatsApp

return hb_socketSend( ::pSocket, cData )

static function StartsWith( cStr, cCompare, nPos )

return SubStr( cStr, nPos, Len( cCompare ) ) == cCompare

static function EndsWith( cStr, cCompare )

return Right( cStr, Len( cCompare ) ) == cCompare

METHOD _Identify( cStr ) CLASS HB_WhatsApp

   local cMsg_identifier := Chr( 0x5D ) + Chr( 0x38 ) + Chr( 0xFA ) + Chr( 0xFC )
   local cServer_delivery_identifier := Chr( 0x8C )
   local cClient_delivery_identifier := Chr( 0x7F ) + Chr( 0xBD ) + Chr( 0xAD )
   local cAcc_info_iden := Chr( 0x99 ) + Chr( 0xBD ) + Chr( 0xA7 ) + Chr( 0x94 )    
   local cLast_seen_ident := Chr( 0x48 ) + Chr( 0x38 ) + Chr( 0xFA ) + Chr( 0xFC )
   local cLast_seen_ident2 := Chr( 0x7B ) + Chr( 0xBD ) + Chr( 0x4C ) + Chr( 0x8B )
   
   if ! ::_is_full_msg( cStr )
      return "incomplete_msg"

   elseif StartsWith( cStr, cMsg_identifier, 4 )

      if EndsWith( cStr, cServer_delivery_identifier )
         return "server_delivery_report"

      elseif EndsWith( cStr, cClient_delivery_identifier )
         return "client_delivery_report"

      else
         return "msg"

      endif

   elseif StartsWith( cStr, cAcc_info_iden, 4 )
      return "account_info"

   elseif StartsWith( cStr, cLast_seen_ident, 4 ) .and. cLast_seen_ident2 $ cStr
      return "last_seen"
   
   else
      return "other"

   endif

return nil

METHOD _Is_Full_Msg( cStr ) CLASS HB_WhatsApp

return Len( cStr ) == Asc( Left( cStr, 1 ) ) + 1

METHOD Destroy() CLASS HB_WhatsApp

   HB_SocketShutDown( ::pSocket )
   HB_SocketClose( ::pSocket )

   ::pSocket = nil

return nil

static function pack_h32( cString )
   
   local c := "", cLeter
   local nibbleshift := 4
   local n
   local nPos   := 0
   local aOut   := {}

   for each cLeter in cString
      n = asc( cLeter )
      if n >= asc( "0" ) .and. n <= asc( "9" )
         n -= asc( "0" )
      elseif n >= asc( "a" ) .and. n <= asc( "f" )
         n -= ( asc( "a" ) - 10 )
      elseif n >= asc( "F" ) .and. n <= asc( "F" )
         n -= ( asc( "A" ) - 10 )
      endif
     
      if cLeter:__enumindex() % 2 != 0
         AAdd( aOut, 0 )        
         nPos++
      endif
     
        aOut[ nPos ] = hb_BitOr( aOut[ nPos ], hb_BitShift( n, nibbleshift ) )
     
      nibbleshift = hb_BitAnd( ( nibbleshift + 4 ), 7 )

      if cLeter:__enumindex() % 2 == 0
         c += Chr( aOut[ nPos ] )
      endif      
     
   next

return c

static function  Num2Days( timet )

return  (timet) / (24.0 * 60.0 * 60.0)

static function  Num2TS( n )
   local fecha, hour, min, sec, time, datetime
   local t2d := Num2Days( n )
   
   fecha = Num2Date( n )
   hour  = ( t2d - int( t2d ) ) * 24
   min   = ( hour - int( hour ) ) * 60
   sec   = ( min - int( min ) ) * 60
   time  = strzero( int( hour ), 2 ) + strzero( int( min ), 2 ) + strzero( int( sec ), 2 )
   datetime = dtos( fecha ) + time
   
return hb_tstostr( hb_stot( datetime ) )

static function Num2Date( n )

   local fecha
   local t2d := Num2Days( n )
   
   fecha := SToD( "19700101" ) + int( t2d )
   
return fecha

static function TS2Num( dt )

   local fecha  
   local nNum
   
   DEFAULT dt := hb_DateTime()
   
   nNum = ( hb_Hour( dt ) * 24 + hb_Minute( dt ) * 60 + hb_sec( dt ) * 60 ) / 86400
     
   nNum += ( hb_TToD( dt ) - SToD( "19700101" ) )
   
   nNum *= 86400
   
   nNum = Int( nNum )
   
return nNum

static function isShort( str )

return Len( str ) < 256

#pragma BEGINDUMP

#include <hbapi.h>

HB_FUNC( STRREV )
{
   int iLen = hb_parclen( 1 ), i;
   char * buffer = ( char * ) hb_xgrab( iLen );
   
   for( i = 0; i < iLen; i++ )
      buffer[ i ] = hb_parc( 1 )[ iLen - i - 1 ];
     
   hb_retclen( buffer, iLen );
   hb_xfree( buffer );
}

#pragma ENDDUMP      
 
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41394
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Enviando mensajes de WhatsApp

Postby José Vicente Beltrán » Fri Aug 17, 2012 6:00 pm

Antinio, no parece problema del puerto, seguiré investigando.

Los equivalentes xHB a las funciones de MESSAGE son:

HB_TSTOSTR' -----> TTOS()
HB_STOT' --------> STOT()
HB_DATETIME' ----------> DATETIME()
HB_HOUR' ----------> HOUR()
HB_MINUTE' ----------> MINUTE()
HB_SEC' -----------> SECS()
HB_TTOD' ------------> TTOD()

Con estos cambios mi EXE se genera correctamente, otra historia es que no consigo mandar nada entre dos Androide
:shock:
Last edited by José Vicente Beltrán on Fri Aug 17, 2012 6:03 pm, edited 1 time in total.
User avatar
José Vicente Beltrán
 
Posts: 282
Joined: Mon Oct 10, 2005 8:55 am
Location: Algeciras, España

Re: Enviando mensajes de WhatsApp

Postby Antonio Linares » Fri Aug 17, 2012 6:00 pm

RequestLastSeen() funciona! Se me pasó mostrar el resultado:

Code: Select all  Expand view
  oWA:RequestLastSeen( "country code and number" )
   ? oWA:LastSeen[ 'seconds_ago' ]
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41394
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Enviando mensajes de WhatsApp

Postby Antonio Linares » Fri Aug 17, 2012 6:03 pm

Jose Vicente,

Muchas gracias por la ayuda portándolo a xHarbour :-)

Si quieres te envio por email mi numero e IMEI para que pruebes con ellos.

A Daniel tambien le esta fallando con su Android, pero con mi numero e IMEI le funciona :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41394
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Enviando mensajes de WhatsApp

Postby José Vicente Beltrán » Fri Aug 17, 2012 6:09 pm

Antonio,
Acepto tu oferta encantado.
jvbp-ARROBA-telefonica.net
:shock:
User avatar
José Vicente Beltrán
 
Posts: 282
Joined: Mon Oct 10, 2005 8:55 am
Location: Algeciras, España

Re: Enviando mensajes de WhatsApp

Postby José Vicente Beltrán » Fri Aug 17, 2012 7:32 pm

Pues después de multiples pruebas probando varios imeis (gracias Antonio) conecta rapidamente con el servidor pero no hay forma de autentificarme.

Si alguien con XHB consigue algo, estaría bien poder confrontar el código, ya que parece que con HB funciona.

saludos :shock:
User avatar
José Vicente Beltrán
 
Posts: 282
Joined: Mon Oct 10, 2005 8:55 am
Location: Algeciras, España

Re: Enviando mensajes de WhatsApp

Postby Cgallegoa » Fri Aug 17, 2012 8:02 pm

Jose Vicente,

Este es el código corregido, compilando y funcionando bien con xHarbour, aunque con Blackberry no pasa nada, devuelve una cadena vacía.

Antonio, si te parece y están bien, por favor puedes incluír los #IFDEF __XHARBOUR__ ? :)

Code: Select all  Expand view
#include "FiveWin.ch"
#include "hbsocket.ch"

#IFDEF __XHARBOUR__
  #xtranslate hb_DateTime([<x,...>])          => DateTime(<x>)
  #xtranslate hb_tstostr([<x>])               => TToS(<x>)
  #xtranslate hb_stot([<x>])                  => SToT(<x>)
  #xtranslate hb_ttod([<x>])                  => TToD(<x>)
  #xtranslate hb_hour([<x>])                  => Hour(<x>)
  #xtranslate hb_minute([<x>])                => Minute(<x>)
  #xtranslate hb_sec([<x>])                   => Secs(<x>)
  #xtranslate hb_NumToHex([<x>])              => NumToHex(<x>)
  #xtranslate hb_StrFormat([<x,...>])         => StrFormat(<x>)
#ENDIF


function Main()

  // local oWA := HB_WhatsApp():New( "country code and number", hb_md5( StrRev( "your IMEI" ) ), "your nickname" )
   local oWA := HB_WhatsApp():New( "5731xxxxx54", hb_md5( StrRev( "354xxxxxxxxxx58" ) ), "Carlos" )

   oWA:Connect()
   oWA:Login()

   ? oWA:cAccount_status, oWA:cAccount_kind, oWA:cAccount_creation, oWA:cAccount_expiration

   oWA:Message( Str( TS2Num() ), "country code and number to send to", "text of the message" )

return nil


CLASS HB_WhatsApp
   DATA  cAccount_status, cAccount_kind, cAccount_creation, cAccount_expiration
   DATA  cNumber, cPassword, cNickname
   DATA  pSocket
   DATA  cServer INIT "s.whatsapp.net"
   DATA  cHost   INIT "bin-short.whatsapp.net"
   DATA  cRealm  INIT "s.whatsapp.net"
   DATA  nPort   INIT 5222
   DATA  cIP
   DATA  cQop    INIT "auth"
   DATA  cDigest_Uri INIT "xmpp/s.whatsapp.net"
   DATA  aResArray
   DATA  cMsg
   DATA  _Incomplete_message

   METHOD New( cNumber, cPassword, cNickname )
   METHOD Connect()
   METHOD Login()
   METHOD Message(cMmsgid,cTo,cTtxt)
   METHOD Read()
   METHOD Send( cData )

   METHOD _Authenticate( cNonce, cNC )
   METHOD _Identify( cStr )
   METHOD _Is_Full_Msg( cStr )
   METHOD parse_account_info( msg )


#IFDEF __XHARBOUR__
   METHOD Destroy()
#ENDIF

   DESTRUCTOR Destroy()

ENDCLASS

METHOD New( cNumber, cPassword, cNickname ) CLASS HB_WhatsApp

   ::cIP = hb_socketGetHosts( ::cHost )[ 1 ]
   ::pSocket = hb_socketOpen()

   ::cNumber   = cNumber
   ::cPassword = cPassword
   ::cNickname = cNickname

return self

METHOD Connect() CLASS HB_WhatsApp

return hb_socketConnect( ::pSocket, { HB_SOCKET_AF_INET, ::cIP, ::nPort } )

static function StrToHex( cStr )

   local n, cHex := ""

   for n = 1 to Len( cStr )
      cHex += "0x" + PadL( hb_NumToHex( Asc( SubStr( cStr, n, 1 ) ) ), "0", 2 )
      if n < Len( cStr )
         cHex += ", "
      endif
   next

return cHex

static function random_uuid()
return hb_StrFormat( "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",;
                     hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ),;
                     hb_Random( 0, 0xffff ),;
                     hb_BitOr( int( hb_Random( 0, 0x0fff ) ), 0x4000 ),;   // *** Cómo hacer el xtranslate de esta línea ??? ***
                     hb_BitOr( int( hb_Random( 0, 0x3fff ) ), 0x8000 ),;
                     hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ), hb_Random( 0, 0xffff ) )


METHOD Login() CLASS HB_WhatsApp

   local cBuffer, cResponse, aArrResponse, hAuthData, cValue, aResData, cResData

   ::Send( "WA" + Chr( 0x01 ) + Chr( 0 ) + Chr( 0 ) + ;
             Chr( 0x19 ) + Chr( 0xF8 ) + Chr( 0x05 ) + Chr( 0x01 ) + ;
             Chr( 0xA0 ) + Chr( 0x8A ) + Chr( 0x84 ) + Chr( 0xFC ) + ;
            // Chr( 0x11 ) + "iPhone-2.6.9-5222" + ;
             Chr( 0 ) + Chr( 0x08 ) + Chr( 0xF8 ) + Chr( 0x02 ) + ;
             Chr( 0x96 ) + Chr( 0xF8 ) + Chr( 0x01 ) + Chr( 0xF8 ) + ;
             Chr( 0x01 ) + Chr( 0x7E ) + Chr( 0 ) + Chr( 0x07 ) + Chr( 0xF8 ) + ;
             Chr( 0x05 ) + Chr( 0x0F ) + Chr( 0x5A ) + Chr( 0x2A ) + ;
             Chr( 0xBD ) + Chr( 0xA7 ) )
            // Chr( 0x11 ) + "iPhone-2.6.9-5222" + ;
            // Chr( 0x11 ) + "BlackBerry-2.7.7151" + ;  // *** Esto será necesario para Blackberry ??? ***
            // Chr( 0x11 ) + "BlackBerry-2.8.1914" + ;

   cBuffer = ::Read()
   cResponse = hb_base64decode( SubStr( cBuffer, 27 ) )
   aArrResponse = HB_ATokens( cResponse, "," )

   hAuthData = {=>}

   for each cValue in aArrResponse
      aResData = hb_ATokens( cValue, "=" )
      hAuthData[ aResData[ 1 ] ] = StrTran( aResData[ 2 ], '"', "" )
   next

   cResData = ::_Authenticate( hAuthData[ "nonce" ] )

   cResponse = Chr( 0x01 ) + Chr( 0x31 ) + Chr( 0xF8 ) + Chr( 0x04 ) + Chr( 0x86 ) + ;
               Chr( 0xBD ) + Chr( 0xA7 ) + Chr( 0xFD ) + Chr( 0 ) + Chr( 1 ) + Chr( 0x28 ) + ;
               hb_base64encode( cResData )
   ::Send( cResponse )

   cBuffer = ::Read()

   ::Read()
   cResponse = Chr( 0 ) + Chr( 8 + Len( ::cNickname ) ) + Chr( 0xF8 ) + Chr( 5 ) + Chr( 0x74 ) + ;
               Chr( 0xA2 ) + Chr( 0xA3 ) + Chr( 0x61 ) + Chr( 0xFC ) + Chr( Len( ::cNickName ) ) + ;
               ::cNickName + Chr( 0 ) + Chr( 0x15 ) + Chr( 0xF8 ) + Chr( 6 ) + Chr( 0x48 ) + ;
               Chr( 0x43 ) + Chr( 5 ) + Chr( 0xA2 ) + Chr( 0x3A ) + Chr( 0xF8 ) + Chr( 1 ) + ;
               Chr( 0xF8 ) + Chr( 4 ) + Chr( 0x7B ) + Chr( 0xBD ) + Chr( 0x4D ) + Chr( 0xF8 ) + ;
               Chr( 1 ) + Chr( 0xF8 ) + Chr( 3 ) + Chr( 0x55 ) + Chr( 0x61 ) + Chr( 0x24 ) + ;
               Chr( 0 ) + Chr( 0x12 ) + Chr( 0xF8 ) + Chr( 8 ) + Chr( 0x48 ) + Chr( 0x43 ) + ;
               Chr( 0xFC ) + Chr( 1 ) + Chr( 0x32 ) + Chr( 0xA2 ) + Chr( 0x3A ) + Chr( 0xA0 ) + ;
               Chr( 0x8A ) + Chr( 0xF8 ) + Chr( 1 ) + Chr( 0xF8 ) + Chr( 3 ) + Chr( 0x1F ) + ;
               Chr( 0xBD ) + Chr( 0xB1 )

        ::Send( cResponse )
        ::Read()

return nil

METHOD _Authenticate( cNonce, cNC ) CLASS HB_WhatsApp

   local cCNonce := random_uuid()
   local cA1 := hb_StrFormat( "%s:%s:%s", ::cNumber, ::cServer, ::cPassword )

   local cA2, cPassword

   if cNC == nil
      cNC = "00000001"
   endif

   cA1 = pack_h32( hb_md5( cA1 ) ) + ":" + cNonce + ":" + cCNonce
   cA2 = "AUTHENTICATE:" + ::cDigest_Uri
   cPassword = hb_md5( cA1 ) + ":" + cNonce + ":" + cNC + ":" + cCNonce + ":" + ::cQop + ;
               ":" + hb_md5( cA2 )
   cPassword = hb_md5( cPassword )

return hb_StrFormat( 'username="%s",realm="%s",nonce="%s",cnonce="%s",nc=%s,qop=%s,digest-uri="%s",response=%s,charset=utf-8',;
                     ::cNumber, ::cRealm, cNonce, cCnonce, cNC, ::cQop, ::cDigest_Uri, cPassword )




METHOD Message( cMsgid, cTo, cTxt ) CLASS HB_WhatsApp
   local lLong_txt_bool := isShort( cTxt )
   local cStream , cMsg
   local cTo_length
   local cMsgid_length
   local cTotal_length

   cTo_length = Chr( Len( cTo ) )
   cMsgid_length = Chr( Len( cMsgid ) )
   cTxt_length = Chr( Len( cTxt ) )

   cContent = Chr( 0xF8 ) + Chr( 0x08 ) + Chr( 0x5D ) + Chr( 0xA0 ) + Chr( 0xFA ) + Chr( 0xFC ) + cTo_length
   cContent += cTo
   cContent += Chr( 0x8A ) + Chr( 0xA2 ) + Chr( 0x1B ) + Chr( 0x43 ) + Chr( 0xFC ) + cMsgid_length
   cContent += cMsgid
   cContent += Chr( 0xF8 ) + Chr( 0x02 ) + Chr( 0xF8 ) + Chr( 0x04 ) + Chr( 0xBA ) + Chr( 0xBD ) + Chr( 0x4F) + ;
               Chr( 0xF8 ) + Chr( 0x01 ) + Chr( 0xF8 ) + Chr( 0x01 ) + Chr( 0x8C ) + Chr( 0xF8 ) + Chr( 0x02 ) + Chr( 0x16 )


   if ! lLong_txt_bool
      cContent += Chr( 0xFD ) + Chr( 0 ) + cTxt_length
   else
      cContent += Chr( 0xFC ) + cTxt_length
   endif

   cContent += cTxt

   cTotal_length = Chr( Len( cContent ) )

   if Len( cTotal_length ) == 1
      cTotal_length = Chr( 0 ) + cTotal_length
   endif

   cMsg := cTotal_length + cContent

   cStream := ::Send(cMsg)
   ::Read()
   // ::Read()
   // ::Read()

Return nil


METHOD Read() CLASS HB_WhatsApp

   local cBuffer := Space( 1024 ), cV, cRcvdType
   local nLen := hb_socketRecv( ::pSocket, @cBuffer )

   cBuffer = SubStr( cBuffer, 1, nLen )
   ::aResArray = HB_ATokens( cBuffer, Chr( 0 ) )
   // ? StrToHex( cBuffer )

   for each cV in ::aResArray
      cRcvdType = ::_Identify( cV )

      // ? cRcvdType
      // ? StrToHex( cV )

      do case
         case cRcvdType == "incomplete_msg"
              ::_incomplete_message = cV

         case cRcvdType == "msg"
              ::cMsg = ::parse_received_message( cV )

         case cRcvdType == "account_info"
              ::parse_account_info( cV )

         case cRcvdType == "last_seen"
              ::lastseen = ::parse_last_seen( cV )
      endcase
   next

return cBuffer

METHOD parse_account_info( cMsg )
   local nAcst, nActkind
   local x := { => }
   local nCreation_timstamp_len, nExpr_length

    cMsg = SubStr( cMsg, 4 )        // Remove Length,F8,second length

#IFDEF __XHARBOUR__
   if Substr( cMsg, 1, 1 ) == Chr( 0x88 )
      cMsg = SubStr( cMsg, 5 )       // Remove Retry Length , i dont think i will need it
   endif
#ELSE
   cMsg = SubStr( cMsg, 5 )        // Remove Success XML
#ENDIF

    // Next should be status
    nAcst = Asc( SubStr( cMsg, 1, 1 ) )
    if nAcst == 0x09
       ::cAccount_status = 'active'
    else
       ::cAccount_status = 'inactive'
    endif
    cMsg = SubStr( cMsg, 3 )        // Remove status & KIND XML
    nActkind = Asc( SubStr( cMsg, 1, 1 ) )
    if nActkind == 0x37
       ::cAccount_kind = 'free'
    else
       ::cAccount_kind = 'paid'
    endif
    cMsg = SubStr( cMsg, 4 )        // Remove XML
    nCreation_timstamp_len = Asc( SubStr( cMsg, 1, 1 ) ) // Should return 10 for the next few thousdands years
    cMsg = SubStr( cMsg, 2 )        // Remove Length
    ::cAccount_creation := Num2TS( Val( SubStr( cMsg, 1, nCreation_timstamp_len ) ) )
    cMsg = SubStr( cMsg, nCreation_timstamp_len + 1 )       // Remove Timestamp
    cMsg = SubStr( cMsg, 3 )        // Remove Expiration XML
    nExpr_length = Asc( SubStr( cMsg, 1, 1 ) ) // Should also be 10
    cMsg = SubStr( cMsg, 2 )        // Remove Length
    ::cAccount_expiration := Num2TS( Val( SubStr( cMsg, 1, nExpr_length ) ) )

return nil


METHOD Send( cData ) CLASS HB_WhatsApp

return hb_socketSend( ::pSocket, cData )

static function StartsWith( cStr, cCompare, nPos )

return SubStr( cStr, nPos, Len( cCompare ) ) == cCompare

static function EndsWith( cStr, cCompare )

return Right( cStr, Len( cCompare ) ) == cCompare

METHOD _Identify( cStr ) CLASS HB_WhatsApp

   local cMsg_identifier := Chr( 0x5D ) + Chr( 0x38 ) + Chr( 0xFA ) + Chr( 0xFC )
   local cServer_delivery_identifier := Chr( 0x8C )
   local cClient_delivery_identifier := Chr( 0x7F ) + Chr( 0xBD ) + Chr( 0xAD )
   local cAcc_info_iden := Chr( 0x99 ) + Chr( 0xBD ) + Chr( 0xA7 ) + Chr( 0x94 )
   local cLast_seen_ident := Chr( 0x48 ) + Chr( 0x38 ) + Chr( 0xFA ) + Chr( 0xFC )
   local cLast_seen_ident2 := Chr( 0x7B ) + Chr( 0xBD ) + Chr( 0x4C ) + Chr( 0x8B )

   if ! ::_is_full_msg( cStr )
      return "incomplete_msg"

   elseif StartsWith( cStr, cMsg_identifier, 4 )

      if EndsWith( cStr, cServer_delivery_identifier )
         return "server_delivery_report"

      elseif EndsWith( cStr, cClient_delivery_identifier )
         return "client_delivery_report"

      else
         return "msg"

      endif

   elseif StartsWith( cStr, cAcc_info_iden, 4 )
      return "account_info"

   elseif StartsWith( cStr, cLast_seen_ident, 4 ) .and. cLast_seen_ident2 $ cStr
      return "last_seen"

   else
      return "other"

   endif

return nil

METHOD _Is_Full_Msg( cStr ) CLASS HB_WhatsApp

return Len( cStr ) == Asc( Left( cStr, 1 ) ) + 1

METHOD Destroy() CLASS HB_WhatsApp

   HB_SocketShutDown( ::pSocket )
   HB_SocketClose( ::pSocket )

   ::pSocket = nil

return nil

static function pack_h32( cString )

   local c := "", cLeter
   local nibbleshift := 4
   local n
   local nPos   := 0
   local aOut   := {}

   for each cLeter in cString
      n = asc( cLeter )
      if n >= asc( "0" ) .and. n <= asc( "9" )
         n -= asc( "0" )
      elseif n >= asc( "a" ) .and. n <= asc( "f" )
         n -= ( asc( "a" ) - 10 )
      elseif n >= asc( "F" ) .and. n <= asc( "F" )
         n -= ( asc( "A" ) - 10 )
      endif

#IFDEF __XHARBOUR__
      if Hb_EnumIndex() % 2 != 0
#ELSE
      if cLeter:__enumindex() % 2 != 0
#ENDIF
         AAdd( aOut, 0 )
         nPos++
      endif

      aOut[ nPos ] = hb_BitOr( aOut[ nPos ], hb_BitShift( n, nibbleshift ) )

      nibbleshift = hb_BitAnd( ( nibbleshift + 4 ), 7 )

#IFDEF __XHARBOUR__
      if Hb_EnumIndex() % 2 == 0
#ELSE
      if cLeter:__enumindex() % 2 == 0
#ENDIF
         c += Chr( aOut[ nPos ] )
      endif

   next

return c

static function  Num2Days( timet )
return  (timet) / (24.0 * 60.0 * 60.0)

static function  Num2TS( n )
   local fecha, hour, min, sec, time, datetime
   local t2d := Num2Days( n )

   fecha = Num2Date( n )
   hour  = ( t2d - int( t2d ) ) * 24
   min   = ( hour - int( hour ) ) * 60
   sec   = ( min - int( min ) ) * 60
   time  = strzero( int( hour ), 2 ) + strzero( int( min ), 2 ) + strzero( int( sec ), 2 )
   datetime = dtos( fecha ) + time

return hb_tstostr( hb_stot( datetime ) )


static function Num2Date( n )
   local fecha
   local t2d := Num2Days( n )

   fecha := SToD( "19700101" ) + int( t2d )

return fecha

static function TS2Num( dt )

   local fecha
   local nNum

   DEFAULT dt := hb_DateTime()

   nNum = ( hb_Hour( dt ) * 24 + hb_Minute( dt ) * 60 + hb_sec( dt ) * 60 ) / 86400

   nNum += ( hb_TToD( dt ) - SToD( "19700101" ) )

   nNum *= 86400

   nNum = Int( nNum )

return nNum

static function isShort( str )
return Len( str ) < 256


#pragma BEGINDUMP

#include <hbapi.h>

HB_FUNC( STRREV )
{
   int iLen = hb_parclen( 1 ), i;
   char * buffer = ( char * ) hb_xgrab( iLen );

   for( i = 0; i < iLen; i++ )
      buffer[ i ] = hb_parc( 1 )[ iLen - i - 1 ];

   hb_retclen( buffer, iLen );
   hb_xfree( buffer );
}

#pragma ENDDUMP
 
Saludos,

Carlos Gallego

*** FWH-23.10, xHarbour 1.2.3 Build 20190603, Borland C++7.30, PellesC ***
Cgallegoa
 
Posts: 425
Joined: Sun Oct 16, 2005 3:32 am
Location: Quito - Ecuador

Re: Enviando mensajes de WhatsApp

Postby Antonio Linares » Fri Aug 17, 2012 8:14 pm

Probado y funcionando correctamente en Windows, Mac y Linux :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 41394
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Enviando mensajes de WhatsApp

Postby mastintin » Fri Aug 17, 2012 8:53 pm

Antonio . No consiguo que me funcione el metodo de customizar el "password" de whatsapp . Lo tengo registrado con iphone y no tengo manera de probar si funciona lo que tengo hecho en el mac . Como mi ingles es pésimo puede que sea algo que hago erróneamente , alguien confirma que el método que comentan funciona ? .
Saludos.
User avatar
mastintin
 
Posts: 1516
Joined: Thu May 27, 2010 2:06 pm

Re: Enviando mensajes de WhatsApp

Postby pcordonet » Sat Aug 18, 2012 8:46 am

Hola Antonio y al resto del foro,

He encontrado este link https://github.com/poliva/WhatsAPI/commits/master

Se estan haciendo cambios más recientes en el codigo php que podrian ser utiles para nosotros implementarlos.

A ver que os parece.

Pere
pcordonet
 
Posts: 111
Joined: Sat Jan 30, 2010 8:35 am
Location: Girona

Re: Enviando mensajes de WhatsApp

Postby José Vicente Beltrán » Sat Aug 18, 2012 2:08 pm

Carlos,
Gracias por el código, lo he comparado con el que yo tenía y observo que quitas la linea

Chr( 0x11 ) + "iPhone-2.6.9-5222" + ;

pero si la quito da un error de array. ¿Cual es la cadena equivalente para Androide?

Gracias de nuevo :shock:
User avatar
José Vicente Beltrán
 
Posts: 282
Joined: Mon Oct 10, 2005 8:55 am
Location: Algeciras, España

Re: Enviando mensajes de WhatsApp

Postby mastintin » Sat Aug 18, 2012 3:18 pm

José Vicente Beltrán wrote:Carlos,
Gracias por el código, lo he comparado con el que yo tenía y observo que quitas la linea

Chr( 0x11 ) + "iPhone-2.6.9-5222" + ;

pero si la quito da un error de array. ¿Cual es la cadena equivalente para Androide?

Gracias de nuevo :shock:


Con datos de un Androide a mi me funciona con la cadena Chr( 0x11 ) + "iPhone-2.6.9-5222" + igualmente.
Saludos.
User avatar
mastintin
 
Posts: 1516
Joined: Thu May 27, 2010 2:06 pm

Re: Enviando mensajes de WhatsApp

Postby José Vicente Beltrán » Sat Aug 18, 2012 3:51 pm

Gracias por contestar Mastintin,
Pués no entiendo muy bién que puede pasar, he repasado todo mil veces, conecta con el servidor, pero no se autentifica y por tanto devuelve una cadena vacía.

Aunque cuando hago las pruebas de conexión el móvil registrado en whatsapp está encendido, entiendo que es indiferente ya que la clave de conexión es el Imei que se manda desde el EXE, ¿Es correcto esto ?
:shock:
User avatar
José Vicente Beltrán
 
Posts: 282
Joined: Mon Oct 10, 2005 8:55 am
Location: Algeciras, España

PreviousNext

Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 33 guests