L
lovellybaby
Unregistered / Unconfirmed
GUEST, unregistred user!
以下是MSN登陆代码,代码不难,但我不知道在Delphi中则么自定义Request头.
-----------------------------------------------------------------------
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Text;
using System.Web;
namespace MSNTestNamespace
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class MSNTest : System.Windows.Forms.Form
{
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Button btnConnect;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label lblUsername;
private System.Windows.Forms.TextBox txtPassword;
private System.Windows.Forms.TextBox txtUsername;
private System.Windows.Forms.Label lblScreenName;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public MSNTest()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.panel1 = new System.Windows.Forms.Panel();
this.btnConnect = new System.Windows.Forms.Button();
this.label2 = new System.Windows.Forms.Label();
this.lblUsername = new System.Windows.Forms.Label();
this.txtPassword = new System.Windows.Forms.TextBox();
this.txtUsername = new System.Windows.Forms.TextBox();
this.lblScreenName = new System.Windows.Forms.Label();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.BackColor = System.Drawing.SystemColors.InactiveBorder;
this.panel1.Controls.Add(this.label2);
this.panel1.Controls.Add(this.lblUsername);
this.panel1.Controls.Add(this.txtPassword);
this.panel1.Controls.Add(this.txtUsername);
this.panel1.Location = new System.Drawing.Point(8, 16);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(192, 144);
this.panel1.TabIndex = 5;
//
// btnConnect
//
this.btnConnect.Location = new System.Drawing.Point(204, 232);
this.btnConnect.Name = "btnConnect";
this.btnConnect.TabIndex = 0;
this.btnConnect.Text = "Connect Me";
this.btnConnect.Click += new System.EventHandler(this.button1_Click);
//
// label2
//
this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
this.label2.Location = new System.Drawing.Point(6, 64);
this.label2.Name = "label2";
this.label2.TabIndex = 8;
this.label2.Text = "Password";
//
// lblUsername
//
this.lblUsername.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
this.lblUsername.Location = new System.Drawing.Point(6, 8);
this.lblUsername.Name = "lblUsername";
this.lblUsername.TabIndex = 7;
this.lblUsername.Text = "Username";
//
// txtPassword
//
this.txtPassword.Location = new System.Drawing.Point(8, 88);
this.txtPassword.Name = "txtPassword";
this.txtPassword.PasswordChar = '*';
this.txtPassword.Size = new System.Drawing.Size(168, 20);
this.txtPassword.TabIndex = 6;
this.txtPassword.Text = "";
//
// txtUsername
//
this.txtUsername.Location = new System.Drawing.Point(8, 32);
this.txtUsername.Name = "txtUsername";
this.txtUsername.Size = new System.Drawing.Size(168, 20);
this.txtUsername.TabIndex = 5;
this.txtUsername.Text = "";
//
// lblScreenName
//
this.lblScreenName.Location = new System.Drawing.Point(8, 168);
this.lblScreenName.Name = "lblScreenName";
this.lblScreenName.Size = new System.Drawing.Size(272, 48);
this.lblScreenName.TabIndex = 6;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.lblScreenName);
this.Controls.Add(this.panel1);
this.Controls.Add(this.btnConnect);
this.Name = "Form1";
this.Text = "MSN Test MSNP9";
this.panel1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new MSNTest());
}
private void button1_Click(object sender, System.EventArgs e)
{
MSNConnection MSN = new MSNConnection();
string username = txtUsername.Text;
string password = txtPassword.Text;
if (username != "" && password != ""
{
lblScreenName.Text = "Connecting please wait";
lblScreenName.Update();
int result = MSN.Connect(username, password);
lblScreenName.Text = "";
lblScreenName.Update();
if (result == 0)
{
MessageBox.Show("Connected as '" + MSN._UserName + "'", "MSN Test",MessageBoxButtons.OK, MessageBoxIcon.Information);
lblScreenName.Text = "Your screenname: " + MSN._ScreenName.Replace("%20", " "
}
else if (result == 401)
{
MessageBox.Show("Invalid credentials, please try again", "MSN Test",MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
MessageBox.Show("Unknow error occured while connecting", "MSN Test",MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
MessageBox.Show("Invalid credentials, please try again", "MSN Test",MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
public class MSNConnection
{
// These are the numbers where the addresses wil appear in the arraylist
// it is not the niced solution, but it works a lot faster
// you can use some kind of IDictionary object to put the value behind a key name
//
// PASPORTURLS
public int DARREALM = 0;
public int DALOGIN = 1;
public int DAREG = 2;
public int PROPERTIES = 3;
public int GENERALDIR = 4;
public int HELP = 5;
public int CONFIGVERSION = 6;
public ArrayList PassportUrls;
/// <summary>
/// Every message from a client has a unique transactionID
/// With every message this number will be increased
/// </summary>
private long _transactionID = 0;
private TcpClient _socket;
private NetworkStream _stream;
private StreamReader _reader;
private StreamWriter _writer;
public string _UserName;
public string _ScreenName;
protected bool DataAvailable
{
get { return _stream.DataAvailable; }
}
public bool Connected
{
get { return _socket != null; }
}
/// <summary>
/// Make a socket connection and streamers
/// </summary>
/// <param name="host">IP host to connect to</param>
/// <param name="port">IP port to connect to</param>
protected void ConnectSocket(string host, int port)
{
Console.WriteLine("Connecting to " + host + ":" + port);
_transactionID = 0;
_socket = new TcpClient(host, port);
_stream = _socket.GetStream();
_reader = new StreamReader(_stream, Encoding.ASCII);
_writer = new StreamWriter(_stream, Encoding.ASCII);
_writer.AutoFlush = true;
}
/// <summary>
/// Write a message to the current socket, this functions raises the transactionID
/// </summary>
/// <param name="line">The Message</param>
/// <param name="writeNewLine">Determine if you write a line, or only a message (with or withhout ending character</param>
private void WriteLine(string line, bool writeNewLine)
{
Console.WriteLine("Writing: " + line);
if (writeNewLine)
_writer.WriteLine(line);
else
_writer.Write(line);
// raise the transactionId
_transactionID++;
}
/// <summary>
/// Write a command to the server
/// </summary>
/// <param name="command">The first command</param>
/// <param name="parameters">The parameters that have to be send to the server</param>
/// <param name="bSendId">Sometimes you don't have to send an transactionID</param>
protected void WriteCommand(string command,string parameters,bool bSendId)
{
string line;
// check what type of format it should be
if (bSendId)
line = string.Format("{0} {1} {2}", command, _transactionID, parameters);
else
line = string.Format("{0} {1}", command, parameters);
// Write the line
WriteLine(line, true);
}
/// <summary>
/// This function read the information from the streamreader
/// and if it read something it returns a new ServerCommand object
/// </summary>
/// <returns>if there is something return new ServerCommand object</returns>
protected ServerCommand ReadCommand()
{
string line = _reader.ReadLine();
Console.WriteLine("Reading: " + line);
if (line == null)
{
Console.WriteLine("Nothing received"
return new ServerCommand();
}
else
{
return new ServerCommand(line);
}
}
/// <summary>
/// This function closes the connection, if its open
/// </summary>
public void Dispose()
{
if( _socket != null )
{
_reader.Close();
_writer.Close();
_stream.Close();
_socket.Close();
_socket = null;
}
}
public int Connect(string UserName, string UserPassword)
{
string host = "messenger.hotmail.com";
int port = 1863;
string ChallengeString;
ServerCommand ServCom;
try
{
while( true )
{
ConnectSocket(host, port);
// Login and provide the current version you want to use
WriteCommand("VER", "MSNP9 CVRO", true);
ServCom = ReadCommand();
// check return value
if (ServCom.CommandName != "VER"
{
return 1;
}
// act like a real msn client and send some information
WriteCommand("CVR","0x0409 win 4.10 i386 MSNMSGR 5.0.0544 MSMSGS " + UserName, true);
ServCom = ReadCommand();
// check return value
if (ServCom.CommandName != "CVR"
{
return 1;
}
// This indicates that you want to connect this user
WriteCommand("USR", "TWN I " + UserName, true);
ServCom = ReadCommand();
// If the server provided the USR answer, than you have got a challenges
// You need this challenge to get a valid clienticket
if (ServCom.CommandName == "USR"
{
ChallengeString = ServCom.Param(3);
break;
}
// if the command is nog XFR, then whe don't know what to do anymore
if (ServCom.CommandName != "XFR"
{
return 1;
}
else
{
Console.WriteLine("Redirected to other server"
}
// If we get here, then we have to change servers, get the IP number
string[] arIP = ServCom.Param(2).Split(':');
host = arIP[0];
// Also get the portnumber
port = int.Parse(arIP[1]);
// close the current connection
Dispose();
}
// Get a valid ticket
string clientticket = GetClientTicket(UserPassword, UserName, ChallengeString);
if (clientticket == "401"
{
// if the code is 401, then most likely there was a error in
// your username password combination
return 401;
}
else if (clientticket == "0"
{
// unknown error occured
return 1;
}
else
{
// finnaly send a valid ticket ID back to the server
WriteCommand("USR", "TWN S " + clientticket, true);
ServCom = ReadCommand();
// if the response is USR <trans> OK then we are succesfully connected
if (ServCom.CommandName != "USR" && ServCom.Param(1) != "OK"
{
return 1;
}
// retrieve the correct username (is always the same, but who cares)
// and retrieve you screenname that you have provided last time
_UserName = ServCom.Param(2);
_ScreenName = ServCom.Param(3);
// Change the status in online, so can other see you come online
WriteCommand("CHG", "NLN", true);
return 0;
}
}
catch (Exception ex)
{
Console.WriteLine("Unknown error occured errocode: " + ex.Message);
return 1;
}
}
/// <summary>
/// This function asks a valid login adres, to connect to
/// </summary>
/// <returns>true if succeed</returns>
public bool GetLoginServerAddres()
{
// Make a request to the server, this adresses are being used in the MSN messenger
HttpWebRequest ServerRequest = (HttpWebRequest)WebRequest.Create("https://nexus.passport.com/rdr/pprdr.asp"
// Get the result
HttpWebResponse ServerResponse = (HttpWebResponse)ServerRequest.GetResponse();
if (ServerResponse.StatusCode == HttpStatusCode.OK)
{
string retrieveddata = ServerResponse.Headers.ToString();
PassportUrls = new ArrayList();
// Pick up the header en split
string[] result = ServerResponse.Headers.Get("PassportURLs".Split(',');
foreach (string s in result)
{
// The actual adres is provided behind the '=' sign
PassportUrls.Add(s.Substring(s.IndexOf('=') + 1));
}
ServerResponse.Close();
return true;
}
else
{
ServerResponse.Close();
return false;
}
}
/// <summary>
/// This function connects to a login server to request a valid ticket,
/// that will be used to login on the MSN servers
/// </summary>
/// <param name="Password">The password of the user, this is just plain text. The connection is HTTPS
/// <param name="Username">The complete username</param>
/// <param name="ChallengeString">A challenge string that you have got, wile connecting to a msn server
/// <returns>a valid ticket, that you send back to the server to get connected</returns>
public string GetClientTicket(string Password, string Username, string ChallengeString)
{
// First get a valid login adres for the initial server
if (GetLoginServerAddres())
{
// On the position of DALOGIN is a valid URL, for login
string uri = "https://" + PassportUrls[DALOGIN];
HttpWebRequest ServerRequest;
HttpWebResponse ServerResponse;
try
{
while( true )
{
Console.WriteLine("Connecting to: " + uri);
// Make a new request
ServerRequest = (HttpWebRequest)HttpWebRequest.Create(uri);
ServerRequest.AllowAutoRedirect = false;
ServerRequest.Pipelined = false;
ServerRequest.KeepAlive = false;
ServerRequest.ProtocolVersion = new Version(1,0);
// Send the authentication header
ServerRequest.Headers.Add("Authorization", "Passport1.4 OrgVerb=GET,OrgURL=http%3A%2F%2Fmessenger%2Emsn%2Ecom,sign-in=" + Username.Replace("@", "%40" + ",pwd=" + Password + "," + ChallengeString + "/n"
// Pick up the result
ServerResponse = (HttpWebResponse)ServerRequest.GetResponse();
// If the statuscode is OK, then there is a valid return
if (ServerResponse.StatusCode == HttpStatusCode.OK)
{
// Pick up the information of the authentications
string AuthenticationInfo = ServerResponse.Headers.Get("Authentication-Info"
// Get the startposition of the ticket id (note it is between two quotes)
int startposition = AuthenticationInfo.IndexOf('/'');
// Get the endposition
int endposition = AuthenticationInfo.LastIndexOf('/'');
// Substract the startposition of the endposition
endposition = endposition - startposition ;
// Close connection
ServerResponse.Close();
// Generate a new substring and return it
return AuthenticationInfo.Substring(startposition + 1, endposition -1 );
}
// If the statuscode is 302, then there is a redirect, read the new adres en connect again
else if (ServerResponse.StatusCode == HttpStatusCode.Found)
{
uri = ServerResponse.Headers.Get("Location"
}
}
}
catch (WebException e)
{
// If the statuscode is 401, then an exeption occurs
// Think that your password + username combination is not correct
// return number so that calling functions knows what to do
if (e.Status == WebExceptionStatus.ProtocolError)
{
return "401";
}
else
{
return "0";
}
}
}
return "0";
}
}
/// <summary>
/// This class is uses, to use the result of the server in a easy way
/// </summary>
public class ServerCommand
{
// The command name of the response
private string _cmdID;
// The entire response
private string _line;
// The parameters of the response (without transactionID, and divided with a space)
private string[] _params;
/// <summary>
/// Constructor for parsing the result line from the streamreader
/// </summary>
/// <param name="line"></param>
public ServerCommand(string line)
{
_line = line;
// always 3 characters command
_cmdID = line.Substring(0, 3);
if (!(_cmdID == "QNG")
{
_params = line.Substring(4).Split(' ');
}
}
/// <summary>
/// This constructor makes a valid object
/// but the command name idicates that there was something wrong
/// </summary>
public ServerCommand()
{
_line = "";
_cmdID = "ERROR";
}
public string CommandName
{
get { return _cmdID; }
}
public string Param(int index)
{
return _params[index];
}
public int ParamCount
{
get { return _params.Length; }
}
public string Line
{
get { return _line; }
}
}
}
------------------------------------------------------------------
-----------------------------------------------------------------------
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Text;
using System.Web;
namespace MSNTestNamespace
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class MSNTest : System.Windows.Forms.Form
{
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Button btnConnect;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label lblUsername;
private System.Windows.Forms.TextBox txtPassword;
private System.Windows.Forms.TextBox txtUsername;
private System.Windows.Forms.Label lblScreenName;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public MSNTest()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.panel1 = new System.Windows.Forms.Panel();
this.btnConnect = new System.Windows.Forms.Button();
this.label2 = new System.Windows.Forms.Label();
this.lblUsername = new System.Windows.Forms.Label();
this.txtPassword = new System.Windows.Forms.TextBox();
this.txtUsername = new System.Windows.Forms.TextBox();
this.lblScreenName = new System.Windows.Forms.Label();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.BackColor = System.Drawing.SystemColors.InactiveBorder;
this.panel1.Controls.Add(this.label2);
this.panel1.Controls.Add(this.lblUsername);
this.panel1.Controls.Add(this.txtPassword);
this.panel1.Controls.Add(this.txtUsername);
this.panel1.Location = new System.Drawing.Point(8, 16);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(192, 144);
this.panel1.TabIndex = 5;
//
// btnConnect
//
this.btnConnect.Location = new System.Drawing.Point(204, 232);
this.btnConnect.Name = "btnConnect";
this.btnConnect.TabIndex = 0;
this.btnConnect.Text = "Connect Me";
this.btnConnect.Click += new System.EventHandler(this.button1_Click);
//
// label2
//
this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
this.label2.Location = new System.Drawing.Point(6, 64);
this.label2.Name = "label2";
this.label2.TabIndex = 8;
this.label2.Text = "Password";
//
// lblUsername
//
this.lblUsername.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
this.lblUsername.Location = new System.Drawing.Point(6, 8);
this.lblUsername.Name = "lblUsername";
this.lblUsername.TabIndex = 7;
this.lblUsername.Text = "Username";
//
// txtPassword
//
this.txtPassword.Location = new System.Drawing.Point(8, 88);
this.txtPassword.Name = "txtPassword";
this.txtPassword.PasswordChar = '*';
this.txtPassword.Size = new System.Drawing.Size(168, 20);
this.txtPassword.TabIndex = 6;
this.txtPassword.Text = "";
//
// txtUsername
//
this.txtUsername.Location = new System.Drawing.Point(8, 32);
this.txtUsername.Name = "txtUsername";
this.txtUsername.Size = new System.Drawing.Size(168, 20);
this.txtUsername.TabIndex = 5;
this.txtUsername.Text = "";
//
// lblScreenName
//
this.lblScreenName.Location = new System.Drawing.Point(8, 168);
this.lblScreenName.Name = "lblScreenName";
this.lblScreenName.Size = new System.Drawing.Size(272, 48);
this.lblScreenName.TabIndex = 6;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.lblScreenName);
this.Controls.Add(this.panel1);
this.Controls.Add(this.btnConnect);
this.Name = "Form1";
this.Text = "MSN Test MSNP9";
this.panel1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new MSNTest());
}
private void button1_Click(object sender, System.EventArgs e)
{
MSNConnection MSN = new MSNConnection();
string username = txtUsername.Text;
string password = txtPassword.Text;
if (username != "" && password != ""
{
lblScreenName.Text = "Connecting please wait";
lblScreenName.Update();
int result = MSN.Connect(username, password);
lblScreenName.Text = "";
lblScreenName.Update();
if (result == 0)
{
MessageBox.Show("Connected as '" + MSN._UserName + "'", "MSN Test",MessageBoxButtons.OK, MessageBoxIcon.Information);
lblScreenName.Text = "Your screenname: " + MSN._ScreenName.Replace("%20", " "
}
else if (result == 401)
{
MessageBox.Show("Invalid credentials, please try again", "MSN Test",MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
MessageBox.Show("Unknow error occured while connecting", "MSN Test",MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
MessageBox.Show("Invalid credentials, please try again", "MSN Test",MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
public class MSNConnection
{
// These are the numbers where the addresses wil appear in the arraylist
// it is not the niced solution, but it works a lot faster
// you can use some kind of IDictionary object to put the value behind a key name
//
// PASPORTURLS
public int DARREALM = 0;
public int DALOGIN = 1;
public int DAREG = 2;
public int PROPERTIES = 3;
public int GENERALDIR = 4;
public int HELP = 5;
public int CONFIGVERSION = 6;
public ArrayList PassportUrls;
/// <summary>
/// Every message from a client has a unique transactionID
/// With every message this number will be increased
/// </summary>
private long _transactionID = 0;
private TcpClient _socket;
private NetworkStream _stream;
private StreamReader _reader;
private StreamWriter _writer;
public string _UserName;
public string _ScreenName;
protected bool DataAvailable
{
get { return _stream.DataAvailable; }
}
public bool Connected
{
get { return _socket != null; }
}
/// <summary>
/// Make a socket connection and streamers
/// </summary>
/// <param name="host">IP host to connect to</param>
/// <param name="port">IP port to connect to</param>
protected void ConnectSocket(string host, int port)
{
Console.WriteLine("Connecting to " + host + ":" + port);
_transactionID = 0;
_socket = new TcpClient(host, port);
_stream = _socket.GetStream();
_reader = new StreamReader(_stream, Encoding.ASCII);
_writer = new StreamWriter(_stream, Encoding.ASCII);
_writer.AutoFlush = true;
}
/// <summary>
/// Write a message to the current socket, this functions raises the transactionID
/// </summary>
/// <param name="line">The Message</param>
/// <param name="writeNewLine">Determine if you write a line, or only a message (with or withhout ending character</param>
private void WriteLine(string line, bool writeNewLine)
{
Console.WriteLine("Writing: " + line);
if (writeNewLine)
_writer.WriteLine(line);
else
_writer.Write(line);
// raise the transactionId
_transactionID++;
}
/// <summary>
/// Write a command to the server
/// </summary>
/// <param name="command">The first command</param>
/// <param name="parameters">The parameters that have to be send to the server</param>
/// <param name="bSendId">Sometimes you don't have to send an transactionID</param>
protected void WriteCommand(string command,string parameters,bool bSendId)
{
string line;
// check what type of format it should be
if (bSendId)
line = string.Format("{0} {1} {2}", command, _transactionID, parameters);
else
line = string.Format("{0} {1}", command, parameters);
// Write the line
WriteLine(line, true);
}
/// <summary>
/// This function read the information from the streamreader
/// and if it read something it returns a new ServerCommand object
/// </summary>
/// <returns>if there is something return new ServerCommand object</returns>
protected ServerCommand ReadCommand()
{
string line = _reader.ReadLine();
Console.WriteLine("Reading: " + line);
if (line == null)
{
Console.WriteLine("Nothing received"
return new ServerCommand();
}
else
{
return new ServerCommand(line);
}
}
/// <summary>
/// This function closes the connection, if its open
/// </summary>
public void Dispose()
{
if( _socket != null )
{
_reader.Close();
_writer.Close();
_stream.Close();
_socket.Close();
_socket = null;
}
}
public int Connect(string UserName, string UserPassword)
{
string host = "messenger.hotmail.com";
int port = 1863;
string ChallengeString;
ServerCommand ServCom;
try
{
while( true )
{
ConnectSocket(host, port);
// Login and provide the current version you want to use
WriteCommand("VER", "MSNP9 CVRO", true);
ServCom = ReadCommand();
// check return value
if (ServCom.CommandName != "VER"
{
return 1;
}
// act like a real msn client and send some information
WriteCommand("CVR","0x0409 win 4.10 i386 MSNMSGR 5.0.0544 MSMSGS " + UserName, true);
ServCom = ReadCommand();
// check return value
if (ServCom.CommandName != "CVR"
{
return 1;
}
// This indicates that you want to connect this user
WriteCommand("USR", "TWN I " + UserName, true);
ServCom = ReadCommand();
// If the server provided the USR answer, than you have got a challenges
// You need this challenge to get a valid clienticket
if (ServCom.CommandName == "USR"
{
ChallengeString = ServCom.Param(3);
break;
}
// if the command is nog XFR, then whe don't know what to do anymore
if (ServCom.CommandName != "XFR"
{
return 1;
}
else
{
Console.WriteLine("Redirected to other server"
}
// If we get here, then we have to change servers, get the IP number
string[] arIP = ServCom.Param(2).Split(':');
host = arIP[0];
// Also get the portnumber
port = int.Parse(arIP[1]);
// close the current connection
Dispose();
}
// Get a valid ticket
string clientticket = GetClientTicket(UserPassword, UserName, ChallengeString);
if (clientticket == "401"
{
// if the code is 401, then most likely there was a error in
// your username password combination
return 401;
}
else if (clientticket == "0"
{
// unknown error occured
return 1;
}
else
{
// finnaly send a valid ticket ID back to the server
WriteCommand("USR", "TWN S " + clientticket, true);
ServCom = ReadCommand();
// if the response is USR <trans> OK then we are succesfully connected
if (ServCom.CommandName != "USR" && ServCom.Param(1) != "OK"
{
return 1;
}
// retrieve the correct username (is always the same, but who cares)
// and retrieve you screenname that you have provided last time
_UserName = ServCom.Param(2);
_ScreenName = ServCom.Param(3);
// Change the status in online, so can other see you come online
WriteCommand("CHG", "NLN", true);
return 0;
}
}
catch (Exception ex)
{
Console.WriteLine("Unknown error occured errocode: " + ex.Message);
return 1;
}
}
/// <summary>
/// This function asks a valid login adres, to connect to
/// </summary>
/// <returns>true if succeed</returns>
public bool GetLoginServerAddres()
{
// Make a request to the server, this adresses are being used in the MSN messenger
HttpWebRequest ServerRequest = (HttpWebRequest)WebRequest.Create("https://nexus.passport.com/rdr/pprdr.asp"
// Get the result
HttpWebResponse ServerResponse = (HttpWebResponse)ServerRequest.GetResponse();
if (ServerResponse.StatusCode == HttpStatusCode.OK)
{
string retrieveddata = ServerResponse.Headers.ToString();
PassportUrls = new ArrayList();
// Pick up the header en split
string[] result = ServerResponse.Headers.Get("PassportURLs".Split(',');
foreach (string s in result)
{
// The actual adres is provided behind the '=' sign
PassportUrls.Add(s.Substring(s.IndexOf('=') + 1));
}
ServerResponse.Close();
return true;
}
else
{
ServerResponse.Close();
return false;
}
}
/// <summary>
/// This function connects to a login server to request a valid ticket,
/// that will be used to login on the MSN servers
/// </summary>
/// <param name="Password">The password of the user, this is just plain text. The connection is HTTPS
/// <param name="Username">The complete username</param>
/// <param name="ChallengeString">A challenge string that you have got, wile connecting to a msn server
/// <returns>a valid ticket, that you send back to the server to get connected</returns>
public string GetClientTicket(string Password, string Username, string ChallengeString)
{
// First get a valid login adres for the initial server
if (GetLoginServerAddres())
{
// On the position of DALOGIN is a valid URL, for login
string uri = "https://" + PassportUrls[DALOGIN];
HttpWebRequest ServerRequest;
HttpWebResponse ServerResponse;
try
{
while( true )
{
Console.WriteLine("Connecting to: " + uri);
// Make a new request
ServerRequest = (HttpWebRequest)HttpWebRequest.Create(uri);
ServerRequest.AllowAutoRedirect = false;
ServerRequest.Pipelined = false;
ServerRequest.KeepAlive = false;
ServerRequest.ProtocolVersion = new Version(1,0);
// Send the authentication header
ServerRequest.Headers.Add("Authorization", "Passport1.4 OrgVerb=GET,OrgURL=http%3A%2F%2Fmessenger%2Emsn%2Ecom,sign-in=" + Username.Replace("@", "%40" + ",pwd=" + Password + "," + ChallengeString + "/n"
// Pick up the result
ServerResponse = (HttpWebResponse)ServerRequest.GetResponse();
// If the statuscode is OK, then there is a valid return
if (ServerResponse.StatusCode == HttpStatusCode.OK)
{
// Pick up the information of the authentications
string AuthenticationInfo = ServerResponse.Headers.Get("Authentication-Info"
// Get the startposition of the ticket id (note it is between two quotes)
int startposition = AuthenticationInfo.IndexOf('/'');
// Get the endposition
int endposition = AuthenticationInfo.LastIndexOf('/'');
// Substract the startposition of the endposition
endposition = endposition - startposition ;
// Close connection
ServerResponse.Close();
// Generate a new substring and return it
return AuthenticationInfo.Substring(startposition + 1, endposition -1 );
}
// If the statuscode is 302, then there is a redirect, read the new adres en connect again
else if (ServerResponse.StatusCode == HttpStatusCode.Found)
{
uri = ServerResponse.Headers.Get("Location"
}
}
}
catch (WebException e)
{
// If the statuscode is 401, then an exeption occurs
// Think that your password + username combination is not correct
// return number so that calling functions knows what to do
if (e.Status == WebExceptionStatus.ProtocolError)
{
return "401";
}
else
{
return "0";
}
}
}
return "0";
}
}
/// <summary>
/// This class is uses, to use the result of the server in a easy way
/// </summary>
public class ServerCommand
{
// The command name of the response
private string _cmdID;
// The entire response
private string _line;
// The parameters of the response (without transactionID, and divided with a space)
private string[] _params;
/// <summary>
/// Constructor for parsing the result line from the streamreader
/// </summary>
/// <param name="line"></param>
public ServerCommand(string line)
{
_line = line;
// always 3 characters command
_cmdID = line.Substring(0, 3);
if (!(_cmdID == "QNG")
{
_params = line.Substring(4).Split(' ');
}
}
/// <summary>
/// This constructor makes a valid object
/// but the command name idicates that there was something wrong
/// </summary>
public ServerCommand()
{
_line = "";
_cmdID = "ERROR";
}
public string CommandName
{
get { return _cmdID; }
}
public string Param(int index)
{
return _params[index];
}
public int ParamCount
{
get { return _params.Length; }
}
public string Line
{
get { return _line; }
}
}
}
------------------------------------------------------------------