MSN Messenger i delphi

hvordan du arbeider med msn messenger protokollen i Delphi
Denne artikkelen er severly utdatert og vil bli oppdatert snart


Dette er en implementering av msn messenger protokollen i delphi det isnt komplett og for å bygge det du trenger WSocket pakken
, det meste av det som presenteres her er en del av spesifikasjonen (fortsatt ikke nok til å selv gjøre en strippet ned MSN Messenger klone). Arbeidet du ser her har sine todos (mest på grunn av det faktum at jeg er rett og slett nytt til stikkontakter programmering), denne artikkelen er basert på verk av venkydude MSN artikkel og en gammel versjon av KMerlin (en opensource msn messenger klone for linux). Dette er den andre artikkelen skriver jeg om Instant Messaging (Den første som om yahoo protokollen, noe wich jeg har ikke vært i stand til å fullføre på grunn av tidspress (mye arbeid)) Jeg planlegger på å oppdatere denne artikkelen så snart som mulige
< --------------------------------- KODE ------------ ---------------------------- >
{GLOBAL TODO: gjennomføring av lokale TODO-tallet, opprydding, utvide}
enhet
MSNMessenger; interfaceuses
WSocket, MD5, klasser, SysUtils; skriv
TUserState = (usOnline, //du er tilkoblet
usBusy, //Egentlig opptatt
usBRB, //Straks tilbake
usAway, //borte fra usOnPhone, //På Phone
usLunch, //Lunsj
usHidden, //Skjult
usOffline //Offline
); TMSNMessenger = class product: (TComponent) privat
FConnected: Boolean; FUserName: String
; FPassword: String
; FFriendlyUserName: String
; Piske: TStrings; FFriendlyNameChange: TNotifyEvent; FState: TUserState; -funksjonen
GetHost: String
; prosedyre
SetHost ( konst
Verdi: String
); -funksjonen
GetPort: String
; prosedyre
SetPort ( konst
Verdi: String
); prosedyre
SetUserName ( konst
Verdi: String
); prosedyre
SetPassWord ( konst
Verdi: String
); -funksjonen
GetFriendlyUserName: String
; prosedyre
SetFriendlyUserName ( konst
Verdi: String
); prosedyre
SetState ( konst
Verdi: TUserState); beskyttet
FSocket: TWSocket; FTrialID: Integer; prosedyre
SendVER; prosedyre
ReceiveSYN; prosedyre
SocketWrite ( konst
AString: String
); prosedyre
LogWrite ( konst
Data: String
); prosedyre
ProcessCommand ( konst
ACommand: String
); prosedyre
SocketDisconnect (Sender: TObject; Feil: Word); prosedyre
SocketDataAvailable (Sender: TObject; Feil: Word); prosedyre
SocketConnect (Sender: TObject; Feil: Word); prosedyre
TriggerFriendlyNameChange; dynamisk
; offentlig konstruktør
Lag (AOwner: TComponent); styre
; destructor
Destroy; styre
; prosedyre
Logg inn; prosedyre
avlogging; publisert eiendom
Host: String lese
GetHost skrive
SetHost; eiendom
havn: String lese
GetPort skrive
SetPort; eiendom
Name: String lese
FUserName skrive
SetUserName; eiendom
Passord: String lese
FPassword skrive
SetPassWord; eiendom
FriendlyUserName: String lese
GetFriendlyUserName skrive
SetFriendlyUserName; eiendom
Tilkoblet: Boolean Les
FConnected; eiendom
Hei: TStrings Les
piske skrive
piske; eiendom
FriendlyNameChange: TNotifyEvent Les
FFriendlyNameChange skrive
FFriendlyNameChange; eiendom
Status: TUserState Les
FState skrive
SetState; slutten
; implementationuses
vinduer; konst
RealState: rekke product: [TUserState] av String
= ( 'CHG% d NLN ',' CHG% d BSY ',' CHG% d BRB ',' CHG% d AWY ',' CHG% d PHN ',' CHG% d LUN ',' CHG% d HDN ',' CHG% d FLN '); skriv
charset = sett med
char; -funksjonen
UTF8ToAnsi (x: string
): ansistring; {Funksjon som mottar UTF8 streng og konverterer til ansi string}
Var
jeg: integer; b1, b2: byte; begynner
Resultat: = x; i: = 1; mens
i < = Lengde (resultater) ikke begynne hvis
(ord (Resultat [i]) og Selge 80 $) < > 0 da begynne
b1: = ord (Resultat [i]); b2: = ord (Resultat [i + 1]); hvis plakater (b1 og Selge $ F0) < > $ C0 deretter
Resultat [i]: = # 128 annet begynne
Resultat [i]: = Chr ((b1 SHL
6) eller
(b2 og Selge $ 3F)); Slett (Resultat, i + 1, 1); slutten
; slutten
; inc (i); slutten
; slutten
; -funksjonen
AnsiToUtf8 (x: ansistring): string
; {Funksjon som mottar ansi streng og konverterer til UTF8 string}
Var
jeg: integer; b1, b2: byte; begynner
Resultat: = x; for
i: = Lengde (resultater) nedfor
en gjøre hvis
Resultat [i] > = # 127 da begynne
b1: = $ C0 eller plakater (ord (Resultat [i]) shr
6); b2: = $ 80 eller plakater (ord (Resultat [i]) og Selge $ 3F); Resultat [i]: = chr (b1); Sett (chr (b2), Resultat, i + 1); slutten
; slutten
; Funksjon
ExtractWord (N: Integer; S: String
; WordDelims: charset): String
; Var
I, J: Word; Count: Integer; SLen: Integer; Begynn
Count: = 0; I: = 1; Resultat: = ''; SLen: = Lengde (S); Mens
I < = SLen Har Begynn
{preskoc oddelovace}
Mens plakater (I < = SLen) og
(S [I] I
WordDelims) Do
Inc (I); {neni-li na končí retezce, Bude nalezen zacatek slova}
Hvis
I < = SLen
Inc (Count); J: = I; {en zde je konec slova}
Mens product: (J < = SLen) Og ikke anbefale (S [J] I
WordDelims) < b> Har
Inc (J); {je-li toto n-te slovo, vloz ho na vystup}
Hvis
Count = N Begynn Så
Resultat: = Kopier (S, I, JI); Avslutt Avslutt
; I: = J; Avslutt
; {mens}
Avslutt
; -funksjonen
WordAt ( konst
Tekst: string
, plassering: Integer): string
; begynner
Resultat: = ExtractWord (Position, Tekst, [ '']); slutten
; {TMSNMessenger}
konstruktør
TMSNMessenger.Create (AOwner: TComponent); begynne arvet
Lag (AOwner); FSocket: = TWSocket.Create (Selv); FSocket.Addr: = 'messenger.hotmail.com'; FSocket.Port: = '1863'; FSocket.Proto: = 'tcp'; FSocket.OnSessionConnected: = SocketConnect; FSocket.OnSessionClosed: = SocketDisconnect; FSocket.OnDataAvailable: = SocketDataAvailable; FConnected: = False; slutten
; destructor
TMSNMessenger.Destroy; begynne
FSocket.Free; FSocket: = nil
; arvet
Destroy; slutten
; -funksjonen
TMSNMessenger.GetFriendlyUserName: String
; begynne hvis ikke anbefale FConnected da
Resultat: = FFriendlyUserName; slutten
; < b> -funksjonen
TMSNMessenger.GetHost: String
; begynner
Resultat: = FSocket.Addr; slutten
; -funksjonen
TMSNMessenger.GetPort : String
; begynner
Resultat: = FSocket.Port; slutten
; prosedyre
TMSNMessenger.Login; begynne
FSocket .Tilkoble; slutten
; prosedyre
TMSNMessenger.Logoff; beginend
; prosedyre
TMSNMessenger.LogWrite ( konst
data: String
); begynne hvis
Assigned (piske) deretter
FLog.Add (data); slutten
; {Processcommand her er beslektet til en windowproc her vi behandler av info alle slags sendes fra serveren som nå det er IFFull (full av hvis tallet) kanskje hvis jeg har litt fritid vil gjøre dette til en sak TODO: Rengjør denne prosedyren rotet opp TODO: Legg mer kommandoer}
prosedyre
TMSNMessenger.ProcessCommand; Var
Tmp: String
; Hash: String
; begynner
Tmp: = WordAt (ACommand, 1); hvis
Tmp = 'VER' deretter
SocketWrite ( 'INF% d'); hvis
Tmp = 'INF' deretter
SocketWrite ( 'USR% d MD5 jeg' + FUserName); hvis
Tmp = 'USR' da begynne hvis
WordAt (ACommand, 4) = 'S' da begynne
Hash: = WordAt (ACommand, 5); Slett (Hash, pos (# 13 # 10, Hash), Lengde (Hash)); Hash: = StrMD5 (Hash + passord); SocketWrite ( 'USR% d MD5 S' + Små bokstaver (Hash)); end annet begynne
FFriendlyUserName: = WordAt (ACommand, 5); SocketWrite ( 'SYN% d 1'); ReceiveSYN; slutten
; slutten
; {Når du mottar en XFR og du ikke er koblet til msn server det betyr omdirigere til en annen server}
hvis plakater (TMP = 'XFR') og ikke anbefale Connected da begynne
TMP: = WordAt (ACommand, 4); FSocket.Close; Slett (TMP, pos ( ':', TMP), Lengde (TMP)); FSocket.Addr: = Tmp; TMP: = WordAt (ACommand, 4); Slett (TMP, 1, pos ( ':', TMP)); FSocket.Port: = Tmp; FSocket.Connect; Gå; slutten
; {Rename Friendly name}
hvis plakater (TMP = 'REA') da begynne
FFriendlyUserName: = WordAt (ACommand, 5); FFriendlyUserName: = StringReplace (FFriendlyUserName, '% 20', '', [rfReplaceall]); TriggerFriendlyNameChange; slutten
; {Den ut kommando mottas før serveren kobler oss, om det er fordi vi har logget på en annen maskin vi mottar budskapet ut OTH (annen maskin) TODO skrive noen hendelse eller noe å hente denne meldingen}
hvis plakater (TMP = 'OUT') da begynne hvis
pos ( 'OTH', ACommand) > 1 deretter
LogWrite ( 'Logget ut i en annen datamaskin frakobling'); slutten
; slutten
; {SYN er uten tvil den mest informationfull MSN Messenger Command SYN informerer oss om: tilgjengelig e vennelisten Block List Omvendt liste (folk som har deg i sine lister) Telefonnumre (Home, mobil osv) MSN Messenger innstillinger etc. men dette kommer med en pris, siden det er så mye informasjon WSocket kan ikke få all info riktig (en kvalitet på blokkeringsfrie stikkontakter) og dermed for for å få det vi vil fryse denne tråden i 5 sekunder (som betyr skjemaene vil ikke motta noen melding, og synes ikke svarer for en stund), jeg vet at det må være en bedre måte rundt hvis noen vet send meg. TODO: Analyser den mottatte innhold TODO: se etter en måte wich trenger ikke å fryse tråden}
prosedyre
TMSNMessenger.ReceiveSYN; Var
Tmp: String
; begynner
FSocket.OnDataAvailable: = nil
; Sleep (5000); Tmp: = FSocket.ReceiveStr; FSocket.OnDataAvailable: = SocketDataAvailable; Tmp: = UTF8ToAnsi (TMP); LogWrite ( 'RECV:' + TMP); SocketWrite ( 'CHG% d NLN'); slutten
; prosedyre
TMSNMessenger.SendVER; begynne
SocketWrite ( 'VER% d CVR0 MSNP5 MSNP6 MSNP7') end
; prosedyre
TMSNMessenger.SetFriendlyUserName ( konst
Verdi: String
); Var
tmp: String
; begynne hvis
FConnected og plakater (FUserName < > Verdi) da begynne
tmp: = StringReplace (verdi, '', '% 20', [ ,,,0],rfReplaceAll]); tmp: = AnsiToUtf8 (TMP); SocketWrite ( 'REA% d' + FUsername + '' + tmp); slutten
; slutten
; prosedyre
TMSNMessenger.SetHost ( konst
Verdi: String
); begynne hvis ikke anbefale Connected så hvis
FSocket.Addr < > Verdi da
FSocket.Addr: = verdi; slutten
; prosedyre
TMSNMessenger.SetPassWord ( konst
Verdi: String
); begynne hvis ikke anbefale Connected så hvis plakater (FPassword < > Verdi) da
FPassword: = Verdi; slutten
; prosedyre
TMSNMessenger.SetPort ( konst
Verdi: String
); begynne hvis ikke anbefale Connected så hvis
FSocket.Port < > Verdi da
FSocket.Port: = verdi; slutten
; prosedyre
TMSNMessenger.SetState ( konst
Verdi: TUserState); begynne hvis
FConnected så hvis plakater (FState < > Verdi) deretter
SocketWrite (RealState [verdi]); slutten
; prosedyre
TMSNMessenger.SetUserName ( konst
Verdi: String
); begynne hvis ikke anbefale FConnected så hvis
FUsername < > Verdi da
FUserName: = verdi; slutten
; prosedyre
TMSNMessenger.SocketConnect (Sender: TObject; Feil: Word); begynner
FTrialID: = 1; SendVER; slutten
; prosedyre
TMSNMessenger.SocketDataAvailable (Sender: TObject; Feil: Word); Var
Tmp: String
; begynne
Tmp: = FSocket.ReceiveStr; Tmp: = UTF8ToAnsi (TMP); LogWrite ( 'RECV:' + TMP); ProcessCommand (TMP); slutten
; prosedyre
TMSNMessenger.SocketDisconnect (Sender: TObject; Feil: Word); begynner
FConnected: = False; LogWrite ( 'Frakoblet'); slutten
; prosedyre
TMSNMessenger.SocketWrite ( konst
AString: String
); begynne
FSocket.SendStr (Format (AString, [FTrialID]) + # 13 + # 10); LogWrite ( 'SENDT:' + Format (AString, [FTrialID])); Inc (FTrialID); slutten
; prosedyre
TMSNMessenger.TriggerFriendlyNameChange; begynne hvis
Assigned (FFriendlyNameChange) da
FFriendlyNameChange(Self);end
;end
.<---------------------------------/CODE---------------------------------------> et eksempel kan være: aMSN: = TMSNMessenger.Create (Selv); //AMSN er en variabel av typen TMSNMessenger AMSN.UserName: = ''; //Dette indikerer brukernavn wich bør alltid være av form *@hotmail.com AMSN.PassWord: = ''; //Dette indikerer passordet AMSN.Log: = MEmo1.Lines; //Logg indikerer et mål å dumpe den mottatte og sendte informasjon, jeg bruker det for å hente protokollinformasjon og sånt, men det er ikke obligatorisk å bruke den AMSN.Login; //Prosedyre wich tilsier at vi bør begynne påloggingen