From e078a2887cf2dc61da49ce302324ff1485f95af9 Mon Sep 17 00:00:00 2001 From: Ian C Date: Mon, 1 Oct 2012 20:59:12 +0000 Subject: Added non-working code for an attempt at FTP --- Noddybox.WindowsPhone.FTP/FTPClient.cs | 828 +++++++++++++++++++++ Noddybox.WindowsPhone.FTP/FTPFile.cs | 125 ++++ Noddybox.WindowsPhone.FTP/FTPFileCollection.cs | 145 ++++ Noddybox.WindowsPhone.FTP/NetException.cs | 84 +++ .../Noddybox.WindowsPhone.FTP.csproj | 69 ++ .../Properties/AssemblyInfo.cs | 37 + Noddybox.WindowsPhone.FTP/ServerDialog.cs | 178 +++++ 7 files changed, 1466 insertions(+) create mode 100644 Noddybox.WindowsPhone.FTP/FTPClient.cs create mode 100644 Noddybox.WindowsPhone.FTP/FTPFile.cs create mode 100644 Noddybox.WindowsPhone.FTP/FTPFileCollection.cs create mode 100644 Noddybox.WindowsPhone.FTP/NetException.cs create mode 100644 Noddybox.WindowsPhone.FTP/Noddybox.WindowsPhone.FTP.csproj create mode 100644 Noddybox.WindowsPhone.FTP/Properties/AssemblyInfo.cs create mode 100644 Noddybox.WindowsPhone.FTP/ServerDialog.cs (limited to 'Noddybox.WindowsPhone.FTP') diff --git a/Noddybox.WindowsPhone.FTP/FTPClient.cs b/Noddybox.WindowsPhone.FTP/FTPClient.cs new file mode 100644 index 0000000..1ae13ce --- /dev/null +++ b/Noddybox.WindowsPhone.FTP/FTPClient.cs @@ -0,0 +1,828 @@ +// This file is part of the Noddybox.WindowsPhone C# suite. +// +// Noddybox.Emulation is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Noddybox.Emulation is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Noddybox.Emulation. If not, see . +// +// Copyright (c) 2012 Ian Cowburn +// +using System; +using System.Text; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Collections.Generic; + +namespace Noddybox.WindowsPhone.Net +{ + /// + /// Provides a simple FTP client interface. Currently only supports IP4. + /// + public class FTPClient + { + // ------------------------------------------------- + // - PUBLIC MEMBERS - + // ------------------------------------------------- + + /// + /// Transfer type + /// + public enum TransferType + { + /// + /// ASCII Data + /// + ASCII, + + /// + /// Binary (image) Data + /// + Binary + }; + + /// + /// Default constructor + /// + public FTPClient(string server_address) + { + passive = false; + connected = true; + welcome = ""; + system = "unknown"; + type = TransferType.Binary; + + passiveAddress = IPAddress.Loopback; + + lastCode=-1; + + try + { + encode = new ASCIIEncoding(); + + server = new ServerDialog(); + + ServerDialog.Reply r; + + commandClient = new TcpClient(server_address,21); + command = commandClient.GetStream(); + + r = BareResult(); + + if (r.Code != 220) + { + connected=false; + commandClient=null; + command=null; + } + } + catch (SocketException e) + { + connected=false; + } + } + + /// + /// Sets timeouts for the command connection + /// + public void SetTimeouts(int recv_timeout, + int send_timeout) + { + recvTimeout=recv_timeout; + sendTimeout=send_timeout; + + if (connected) + { + commandClient.ReceiveTimeout=recv_timeout; + commandClient.SendTimeout=send_timeout; + } + } + + /// + /// Set/get whether to use passive mode + /// + public bool Passive + { + get {return passive;} + + set + { + passive=value; + } + } + + /// + /// Set/get the IP address to offer in non-passive mode + /// + public IPAddress NonPassiveIP + { + get {return passiveAddress;} + + set + { + passiveAddress=value; + } + } + + /// + /// Logon to the FTP server + /// + public bool Logon(string username,string password) + { + ServerDialog.Reply r; + + r=SendCommand("USER "+username); + + if (r.Code==331) + { + r=SendCommand("PASS "+password); + } + + if (r.Code==230) + { + SendCommand("SYST"); + } + else + { + return false; + } + + return true; + } + + /// + /// Whether connected to the FTP server + /// + public bool Connected + { + get {return connected;} + } + + /// + /// The welcome text after logging on + /// + public string Welcome + { + get {return welcome;} + } + + /// + /// The system type. Note the entire system response is + /// returned. If you want just the first word, string.split() + /// it. + /// + public string System + { + get {return system;} + } + + /// + /// The transfer type + /// + public TransferType Type + { + get + { + return type; + } + + set + { + type=value; + + switch(type) + { + case TransferType.ASCII: + SendCommand("TYPE A"); + break; + + case TransferType.Binary: + SendCommand("TYPE I"); + break; + } + } + } + + /// + /// Get the current working directory + /// + public string Pwd + { + get + { + string pwd=""; + + ServerDialog.Reply r=SendCommand("PWD"); + + if (r.Code==257) + { + pwd=ParseQuote(r.Text); + } + + return pwd; + } + } + + /// + /// Change directory to the parent directory + /// + public bool CDUp() + { + return SendCommand("CDUP").Code==250; + } + + /// + /// Change directory + /// + public bool CD(string dir) + { + return SendCommand("CWD "+dir).Code==250; + } + + /// + /// Get a list of the filenames in the current directory + /// + public StringCollection Dir() + { + StringCollection l=new StringCollection(); + ServerDialog.Reply r; + TransferType old_type=type; + + PrepareData(); + + Type=TransferType.ASCII; + + r=SendCommand("NLST"); + + if (r.Code==150 || r.Code==125) + { + OpenData(); + + string s=GetDataString(); + string fn=""; + + foreach (char c in s) + { + if (c=='\n') + { + l.Add(fn.TrimEnd(null)); + fn=""; + } + else + { + fn+=c; + } + } + + CloseData(); + } + + BareResult(); + + Type=old_type; + + return l; + } + + /// + /// Get a detailed list of the filenames in the current directory. + /// The list returned is made up of FTPFile classes. + /// + public FTPFileCollection DirEx() + { + StringCollection l=Dir(); + FTPFileCollection al=new FTPFileCollection(); + + foreach(string s in l) + { + FTPFile.FileType type=FTPFile.FileType.File; + ulong size; + + // See if it's a directory by seeing if CD works + // + if (CD(s)) + { + type=FTPFile.FileType.Dir; + size=0; + CDUp(); + } + else + { + ServerDialog.Reply r; + + // Get the file size + // + r=SendCommand("SIZE "+s); + + if (r.Code==213) + { + size=Convert.ToUInt64(r.Text); + } + else + { + size=UInt64.MaxValue; + } + } + + al.Add(new FTPFile(s,type,size)); + } + + al.Sort(); + + return al; + } + + /// + /// Delete a specified file + /// + public bool Delete(string name) + { + return SendCommand("DELE "+name).Code==250; + } + + /// + /// Delete a specified directory + /// + public bool Rmdir(string name) + { + return SendCommand("RMD "+name).Code==250; + } + + /// + /// Create a specified directory + /// + public bool Mkdir(string name) + { + return SendCommand("MKD "+name).Code==257; + } + + /// + /// Rename a specified file + /// + public bool Rename(string old_name, string new_name) + { + ServerDialog.Reply r; + + r=SendCommand("RNFR "+old_name); + + if (r.Code!=350) + { + return false; + } + + r=SendCommand("RNTO "+new_name); + + if (r.Code!=250) + { + return false; + } + + return true; + } + + /// + /// Gets a file as a byte array + /// + public byte[] Get(string name) + { + ArrayList al=new ArrayList(); + + PrepareData(); + + ServerDialog.Reply r=SendCommand("RETR "+name); + + if (r.Code==150 || r.Code==125) + { + OpenData(); + GetData(al); + CloseData(); + } + else + { + return null; + } + + BareResult(); + + // Surely there must be a better way... + // + int count=al.Count; + byte[] file=new byte[count]; + + for(int f=0;f + /// Gets a file and stores it in a local file + /// + public bool Get(string name, string local_name) + { + byte[] data=Get(name); + + if (data==null) + { + return false; + } + + FileStream file=new FileStream(local_name,FileMode.Create); + BinaryWriter bin=new BinaryWriter(file); + + bin.Write(data); + + bin.Close(); + + return true; + } + + /// + /// Puts a file as a byte array + /// + public bool Put(string name, byte[] data) + { + PrepareData(); + + ServerDialog.Reply r=SendCommand("STOR "+name); + + if (r.Code==150 || r.Code==125) + { + OpenData(); + PutData(data); + CloseData(); + } + else + { + return false; + } + + r=BareResult(); + + return r.Code==226; + } + + /// + /// Puts a file and from a local file + /// + public bool Put(string name, string local_name) + { + if (!File.Exists(local_name)) + { + return false; + } + + FileInfo info=new FileInfo(local_name); + + FileStream file=new FileStream(local_name,FileMode.Open,FileAccess.Read); + BinaryReader bin=new BinaryReader(file); + + byte[] data=bin.ReadBytes((int)info.Length); + bin.Close(); + + return Put(name,data); + } + + /// + /// The last code returned by the server (see RFC 959) + /// + public int LastCode + { + get {return lastCode;} + } + + /// + /// Quit and disconnect from the server. + /// + public void Quit() + { + if (connected) + { + SendCommand("QUIT"); + command.Close(); + } + } + + // ------------------------------------------------- + // - PRIVATE MEMBERS - + // ------------------------------------------------- + + private bool connected; + private TcpClient commandClient; + private Socket data; + private Socket nonPassive; + private IPEndPoint dataAddr; + private NetworkStream command; + private string welcome; + private string system; + private int lastCode; + private ServerDialog server; + private int recvTimeout; + private int sendTimeout; + private ASCIIEncoding encode; + private bool passive; + private TransferType type; + private IPAddress passiveAddress; + + private string ParseQuote(string s) + { + string r=""; + bool in_quote=false; + + foreach (char c in s) + { + if (c=='\"') + { + in_quote=!in_quote; + } + else + { + if (in_quote) + { + r+=c; + } + } + } + + return r; + } + + private IPEndPoint ParseAddress(string s) + { + string r=""; + bool in_quote=false; + + foreach (char c in s) + { + if (c=='(' || c==')') + { + in_quote=!in_quote; + } + else + { + if (in_quote) + { + r+=c; + } + } + } + + char[] sep=new char[1] {','}; + string[] arg=r.Split(sep); + + if (arg.Length!=6) + { + throw new NetException(NetException.Type.FTP_BadReplyAddress); + } + + int port=Convert.ToInt32(arg[4])*256+Convert.ToInt32(arg[5]); + + IPEndPoint ip=new IPEndPoint(IPAddress.Parse(arg[0] + "." + + arg[1] + "." + + arg[2] + "." + + arg[3]), + port); + + return ip; + } + + private void PrepareData() + { + if (passive) + { + ServerDialog.Reply r=SendCommand("PASV"); + + if (r.Code!=227) + { + throw new NetException(NetException.Type.FTP_NoPassive); + } + + dataAddr=ParseAddress(r.Text); + + DebugOut("PASV told to use " + dataAddr.ToString()); + + data=new Socket(AddressFamily.InterNetwork, + SocketType.Stream, + ProtocolType.Tcp); + + data.Connect(dataAddr); + } + else + { + if (nonPassive==null) + { + try + { + nonPassive=new Socket(AddressFamily.InterNetwork, + SocketType.Stream, + ProtocolType.Tcp); + + if (passiveAddress==IPAddress.None) + { + IPAddress[] host=Dns.Resolve(Dns.GetHostName()).AddressList; + + if (host.Length==0) + { + throw new NetException(NetException.Type.ALL_NoLocalIP); + } + + passiveAddress=host[0]; + } + + IPEndPoint ep=new IPEndPoint(passiveAddress,0); + + nonPassive.Bind(ep); + + ep=(IPEndPoint)nonPassive.LocalEndPoint; + + byte[] a=ep.Address.GetAddressBytes(); + int p=ep.Port; + + int p1=p>>8; + int p2=p&0xff; + + string portCmd="PORT " + + a[0].ToString() + "," + + a[1].ToString() + "," + + a[2].ToString() + "," + + a[3].ToString() + "," + + p1.ToString() + "," + + p2.ToString(); + + ServerDialog.Reply r=SendCommand(portCmd); + + if (r.Code!=200) + { + nonPassive.Close(); + nonPassive=null; + throw new NetException + (NetException.Type.FTP_NonPassiveProblem); + } + + nonPassive.Listen(5); + } + catch (SocketException e) + { + nonPassive=null; + throw e; + } + } + } + } + + private void OpenData() + { + if (passive) + { + // Connection already created by PrepareData() + } + else + { + // TODO : This could actually block indefinitely + // + data=nonPassive.Accept(); + + if (data==null) + { + throw new NetException + (NetException.Type.FTP_NonPassiveProblem); + } + } + } + + private void CloseData() + { + DebugOut("Closing data connection"); + + data.Shutdown(SocketShutdown.Both); + data.Close(); + data=null; + + if (!passive) + { + DebugOut("Closing non-passive listener"); + + nonPassive.Close(); + nonPassive=null; + } + } + + private string GetDataString() + { + byte[] buff=new byte[1024]; + string result=""; + + while(true) + { + int len=data.Receive(buff,buff.Length,SocketFlags.None); + + DebugOut("Read " + len.ToString() + " bytes from data connection"); + + if (len==0) + { + break; + } + + result+=encode.GetString(buff,0,len); + } + + DebugOut("Read string '" + result + "' data connection"); + + return result; + } + + private void GetData(ArrayList al) + { + byte[] buff=new byte[1024]; + + while(true) + { + int len=data.Receive(buff,buff.Length,SocketFlags.None); + + DebugOut("Read " + len.ToString() + " bytes from data connection"); + + if (len==0) + { + break; + } + + // This whole idea needs sorting - this will be painful + // + for(int f=0;f-1) + { + lastCode=r.Code; + } + + switch(r.Code) + { + case 215: + system = r.Text; + break; + + case 230: + welcome = r.Text; + break; + + default: + break; + } + } + } +} diff --git a/Noddybox.WindowsPhone.FTP/FTPFile.cs b/Noddybox.WindowsPhone.FTP/FTPFile.cs new file mode 100644 index 0000000..61ab481 --- /dev/null +++ b/Noddybox.WindowsPhone.FTP/FTPFile.cs @@ -0,0 +1,125 @@ +// This file is part of the Noddybox.WindowsPhone C# suite. +// +// Noddybox.Emulation is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Noddybox.Emulation is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Noddybox.Emulation. If not, see . +// +// Copyright (c) 2012 Ian Cowburn +// +using System; + +namespace Noddybox.WindowsPhone.Net +{ + using System; + + /// + /// Provides the file info type returned by FTPClient + /// + public class FTPFile : IComparable + { + // ------------------------------------------------- + // - PUBLIC MEMBERS - + // ------------------------------------------------- + + /// + /// File type + /// + public enum FileType + { + /// + /// Directory + /// + Dir, + + /// + /// File + /// + File + }; + + /// + /// Constructor + /// + public FTPFile(string name, FileType type, ulong size) + { + m_type=type; + m_name=name; + m_size=size; + } + + /// + /// The name of the file + /// + public string Name + { + get {return m_name;} + } + + /// + /// The type of the file + /// + public FileType Type + { + get {return m_type;} + } + + /// + /// The size of the file (returns 0 for directories) + /// + public ulong Size + { + get + { + if (m_type==FileType.Dir) + { + return 0; + } + else + { + return m_size; + } + } + } + + /// + /// Compares instance + /// + int IComparable.CompareTo(object o) + { + if (o is FTPFile) + { + FTPFile f=(FTPFile)o; + + if (m_type==FileType.Dir && f.m_type!=FileType.Dir) + { + return -1; + } + + if (m_type==FileType.File && f.m_type!=FileType.File) + { + return 1; + } + + return m_name.CompareTo(f.m_name); + } + + throw new ArgumentException("object not an FTPFile"); + } + + // ------------------------------------------------- + // - PRIVATE MEMBERS - + // ------------------------------------------------- + private FileType m_type; + private ulong m_size; + private string m_name; + } +} diff --git a/Noddybox.WindowsPhone.FTP/FTPFileCollection.cs b/Noddybox.WindowsPhone.FTP/FTPFileCollection.cs new file mode 100644 index 0000000..1f8d4cb --- /dev/null +++ b/Noddybox.WindowsPhone.FTP/FTPFileCollection.cs @@ -0,0 +1,145 @@ +// This file is part of the Noddybox.WindowsPhone C# suite. +// +// Noddybox.Emulation is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Noddybox.Emulation is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Noddybox.Emulation. If not, see . +// +// Copyright (c) 2012 Ian Cowburn +// +using System; +using System.Collections.Generic; + +namespace Noddybox.WindowsPhone.Net +{ + /// + /// Collection of FTPFile objects + /// + public class FTPFileCollection : IEnumerable + { + // ------------------------------------------------- + // - PUBLIC MEMBERS - + // ------------------------------------------------- + + /// + /// Default constructor - initializes all fields to default values + /// + public FTPFileCollection() + { + m_list = new List(); + } + + /// + /// Number of files in the collection + /// + public int Count + { + get {return m_list.Count;} + } + + /// + /// Add a file to the collection + /// + public void Add(FTPFile f) + { + m_list.Add(f); + } + + /// + /// Get a file from the collection + /// + public FTPFile Get(int index) + { + return (FTPFile)m_list[index]; + } + + /// + /// Sort the collection + /// + public void Sort() + { + m_list.Sort(); + } + + /// + /// Get iterator + /// + public Enum GetEnumerator() + { + return new Enum(this); + } + + /// + /// Get iterator + /// + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// Class for enumeration + /// + public class Enum : IEnumerator + { + /// + /// Default constructor - initializes all fields to default values + /// + public Enum(FTPFileCollection c) + { + m_index=-1; + m_col=c; + } + + /// + /// See IEnumerator + /// + public bool MoveNext() + { + m_index++; + return m_index + /// See IEnumerator + /// + public FTPFile Current + { + get {return m_col.Get(m_index);} + } + + /// + /// See IEnumerator + /// + public void Reset() + { + m_index=-1; + } + + /// + /// See IEnumerator + /// + object IEnumerator.Current + { + get {return Current;} + } + + private int m_index; + private FTPFileCollection m_col; + } + + // ------------------------------------------------- + // - PRIVATE MEMBERS - + // ------------------------------------------------- + + private List m_list; + } +} diff --git a/Noddybox.WindowsPhone.FTP/NetException.cs b/Noddybox.WindowsPhone.FTP/NetException.cs new file mode 100644 index 0000000..119c241 --- /dev/null +++ b/Noddybox.WindowsPhone.FTP/NetException.cs @@ -0,0 +1,84 @@ +// This file is part of the Noddybox.WindowsPhone C# suite. +// +// Noddybox.Emulation is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Noddybox.Emulation is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Noddybox.Emulation. If not, see . +// +// Copyright (c) 2012 Ian Cowburn +// +using System; + +namespace Noddybox.WindowsPhone.Net +{ + /// + /// Exception raised for internal problems. + /// + public class NetException : System.Exception + { + /// + /// The types of error that can be raised + /// + public enum Type + { + /// + /// A server replied with no code in the first reply line + /// + ALL_NoReplyCode, + + /// + /// The local IP address could not be found (note that all + /// the routines use the first available IP when onew must + /// be chosen). + /// + ALL_NoLocalIP, + + /// + /// An uncompleted feature was used + /// + ALL_NotImplemented, + + /// + /// The FTP server does not support passive connections + /// + FTP_NoPassive, + + /// + /// The FTP server had a problem accepting our local port + /// info + /// + FTP_NonPassiveProblem, + + /// + /// Given a bad address by the server + /// + FTP_BadReplyAddress + }; + + /// + /// Default constructor - initializes all fields to default values + /// + public NetException(Type e) + { + m_code=e; + } + + /// + /// Gets the cause of the error + /// + public Type Error + { + get {return m_code;} + } + + private Type m_code; + } +} diff --git a/Noddybox.WindowsPhone.FTP/Noddybox.WindowsPhone.FTP.csproj b/Noddybox.WindowsPhone.FTP/Noddybox.WindowsPhone.FTP.csproj new file mode 100644 index 0000000..0c9453b --- /dev/null +++ b/Noddybox.WindowsPhone.FTP/Noddybox.WindowsPhone.FTP.csproj @@ -0,0 +1,69 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {31A42B81-8DF6-41FD-AB0A-7F90388DFB7A} + {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + Properties + Noddybox.WindowsPhone.FTP + Noddybox.WindowsPhone.FTP + v4.0 + $(TargetFrameworkVersion) + WindowsPhone71 + Silverlight + false + true + true + + + true + full + false + Bin\Debug + DEBUG;TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + pdbonly + true + Bin\Release + TRACE;SILVERLIGHT;WINDOWS_PHONE + true + true + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Noddybox.WindowsPhone.FTP/Properties/AssemblyInfo.cs b/Noddybox.WindowsPhone.FTP/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..158de02 --- /dev/null +++ b/Noddybox.WindowsPhone.FTP/Properties/AssemblyInfo.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Noddybox.WindowsPhone.FTP")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Noddybox.WindowsPhone.FTP")] +[assembly: AssemblyCopyright("Copyright © 2012")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("3e489c9b-66bf-41c9-bfe5-54cdf00d2afe")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: NeutralResourcesLanguageAttribute("en-US")] diff --git a/Noddybox.WindowsPhone.FTP/ServerDialog.cs b/Noddybox.WindowsPhone.FTP/ServerDialog.cs new file mode 100644 index 0000000..4291afb --- /dev/null +++ b/Noddybox.WindowsPhone.FTP/ServerDialog.cs @@ -0,0 +1,178 @@ +// This file is part of the Noddybox.WindowsPhone C# suite. +// +// Noddybox.Emulation is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Noddybox.Emulation is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Noddybox.Emulation. If not, see . +// +// Copyright (c) 2012 Ian Cowburn +// +using System; +using System.Net; +using System.Net.Sockets; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; + +namespace Noddybox.WindowsPhone.Net +{ + /// + /// Provides a wrapper around a stream to interact with servers + /// + public class ServerDialog + { + // ------------------------------------------------- + // - PUBLIC MEMBERS - + // ------------------------------------------------- + + /// + /// Used for returns from the server + /// + public class Reply + { + /// + /// Default constructor - initializes all fields to default values + /// + public Reply() + { + m_code=-1; + m_text=""; + } + + /// + /// The code returned by the server + /// + public int Code + { + get {return m_code;} + set {m_code=value;} + } + + /// + /// The text returned by the server + /// + public string Text + { + get {return m_text;} + set {m_text=value;} + } + + private int m_code; + private string m_text; + + } + + /// + /// Default constructor - initializes all fields to default values + /// + public ServerDialog() + { + m_encode=new System.Text.ASCIIEncoding(); + m_code=new Regex("^[0-9][0-9][0-9]"); + m_code_end=new Regex("^[0-9][0-9][0-9][^-]"); + + } + + /// + /// Sends a command to the server and returns the reply + /// + public Reply Send(Stream str, string command) + { + Reply r=new Reply(); + + if (command!=null) + { + byte[] b=ToBytes(command); + + str.Write(b,0,b.Length); + } + + GetResult(str,r); + + return r; + } + + // ------------------------------------------------- + // - PRIVATE MEMBERS - + // ------------------------------------------------- + + private ASCIIEncoding m_encode; + private Regex m_code; + private Regex m_code_end; + + + + private byte[] ToBytes(string s) + { + return m_encode.GetBytes(s); + } + + private string GetLine(Stream str) + { + byte[] b=new byte[1]; + int c; + string r=""; + + while((c=str.ReadByte())!=-1) + { + b[0]=(byte)c; + r+=m_encode.GetString(b); + + if (c==10) + { + break; + } + } + + return r; + } + + private void GetResult(Stream str, Reply r) + { + string s; + string all=""; + bool first_line=true; + + do + { + s=GetLine(str); + + if (first_line) + { + if (m_code.IsMatch(s)) + { + r.Code=Convert.ToInt32(s.Substring(0,3)); + } + else + { + throw new NetException(NetException.Type.ALL_NoReplyCode); + } + + first_line=false; + } + + if (m_code.IsMatch(s)) + { + all+=s.Substring(4); + } + else + { + all+=s; + } + + } while (!m_code_end.IsMatch(s)); + + all=all.TrimEnd(null); + r.Text=all; + } + + } +} -- cgit v1.2.3