[Icrontic] ftpupload.cs
Code:
/*
About: Script to upload files from shard-server on a regular basis. No need to install IIS or Apache on the shard-server anymore to display the status.html .
Will not "lag" shard like many other ftp-scripts do. Why? Thread support :)
This scripts on RunUO version <=1.0.0 .
Version: 0.1.3 (final)
Author: FTP upload-script based on ftpuploader.cs by unknown (Ryan's ftp-upload? cant remember).
Modification by Spuno (threading) & Xan for Icronticshard.com.
New in this version: Threading support. Doesnt lock-up your shard anymore while uploading.
More original & cool "old-scripts" to be released from the Icronticshard.com official codebase.
Version history:
0.1.3 - Added a function to see amount of data uploaded. Writes to console.
0.1.2 - Fixed bug with close(); breaking upload.
0.1.1 - Fixed some issues with threading. Timer is borked. Fixed!
0.1.0 - Original script. Unknown version, so Im assigning it 0.1.0 Im guessing this is Ryan's ftpupload script, but it's no longer available on RunUO forums (using search).
*/
using Server;
using System;
using System.Net;
using System.IO;
using System.Text;
using System.Net.Sockets;
using System.Threading;
namespace FtpLib
{
public class FTP
{
private string remoteHost, remotePath, remoteUser, remotePass, msg;
public string localpath;
public double starttime, delaytime;
private int remotePort,bytes;
private Socket clientSocket;
private int retValue;
private Boolean logined;
private string reply;
private static int BLOCK_SIZE = 512;
Byte[] buffer = new Byte[BLOCK_SIZE];
Encoding ASCII = Encoding.ASCII;
//Spunos fulhack (ugly hack)
public string FileName = "";
public bool Resume = false;
public FTP()
{
/* Modify these value to suite your needs */
remoteHost = "x.x.x.x"; // ip to remote-server
remotePath = "/path/on/server";
localpath = @"C:/RunUO 1.0/web/status.html";
remoteUser = "username";
remotePass = "password";
remotePort = 21; // ftp-port
starttime = 30.0; // how many seconds after shard up you want this to start.
delaytime = 60.0; // how many seconds between each upload.
logined = false;
}
public void login()
{
clientSocket = new
Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
IPEndPoint ep = new
IPEndPoint(Dns.Resolve(remoteHost).AddressList[0], remotePort);
try
{
clientSocket.Connect(ep);
}
catch(Exception)
{
throw new IOException("Couldn't connect to remote server");
}
readReply();
if(retValue != 220)
{
close();
throw new IOException(reply.Substring(4));
}
sendCommand("USER "+remoteUser);
if( !(retValue == 331 || retValue == 230) )
{
cleanup();
throw new IOException(reply.Substring(4));
}
if( retValue != 230 )
{
sendCommand("PASS "+remotePass);
if( !(retValue == 230 || retValue == 202) )
{
cleanup();
throw new IOException(reply.Substring(4));
}
}
logined = true;
Console.WriteLine("Connected to "+remoteHost);
chdir(remotePath);
}
public void setBinaryMode(Boolean mode)
{
if(mode)
{
sendCommand("TYPE I");
}
else
{
sendCommand("TYPE A");
}
if (retValue != 200)
{
throw new IOException(reply.Substring(4));
}
}
public void Thread_Upload(string _Filename, bool _Resume)
{
this.FileName = _Filename;
this.Resume = _Resume;
Thread T = new Thread(new ThreadStart(Upload));
T.Start();
}
public void Upload()
{
this.upload(this.FileName,this.Resume);
}
public void upload(string fileName)
{
upload(fileName,false);
}
public long getFileSize(string fileName)
{
if(!logined)
{
login();
}
sendCommand("SIZE " + fileName);
long size=0;
if(retValue == 213)
{
size = Int64.Parse(reply.Substring(4));
}
else
{
throw new IOException(reply.Substring(4));
}
return size;
}
public void upload(string fileName,Boolean resume)
{
if(!logined)
{
login();
}
Socket cSocket = createDataSocket();
long offset=0;
if(resume)
{
try
{
setBinaryMode(true);
offset = getFileSize(fileName);
}
catch(Exception)
{
offset = 0;
}
}
if(offset > 0 )
{
sendCommand("REST " + offset);
if(retValue != 350)
{
offset = 0;
}
}
sendCommand("STOR "+Path.GetFileName(fileName));
if( !(retValue == 125 || retValue == 150) )
{
throw new IOException(reply.Substring(4));
}
FileStream input = new
FileStream(fileName,FileMode.Open);
if(offset != 0)
{
input.Seek(offset,SeekOrigin.Begin);
}
Console.WriteLine("Uploading file "+fileName+" to "+remotePath);
World.Broadcast( 0x35, true, "Updating shard-status at [url]www.icronticshard.com[/url] !" );
int byt=0;
while ((bytes = input.Read(buffer,0,buffer.Length)) > 0)
{
byt += buffer.Length;
cSocket.Send(buffer, bytes, 0);
//if(byt % 1000000 == 0)
Console.WriteLine(byt + " bytes sent");
}
input.Close();
Console.WriteLine("");
if (cSocket.Connected)
{
cSocket.Close();
}
readReply();
if( !(retValue == 226 || retValue == 250) )
{
throw new IOException(reply.Substring(4));
}
}
public void chdir(string dirName)
{
if(dirName.Equals("."))
{
return;
}
if(!logined)
{
login();
}
sendCommand("CWD "+dirName);
if(retValue != 250)
{
throw new IOException(reply.Substring(4));
}
this.remotePath = dirName;
Console.WriteLine("Current directory is "+remotePath);
}
public void close()
{
if( clientSocket != null )
{
sendCommand("QUIT");
}
cleanup();
Console.WriteLine("Closing FTP connection...");
}
private void readReply()
{
msg = "";
reply = readLine();
retValue = Int32.Parse(reply.Substring(0,3));
}
private void cleanup()
{
if(clientSocket!=null)
{
clientSocket.Close();
clientSocket = null;
}
logined = false;
}
private string readLine()
{
while(true)
{
bytes = clientSocket.Receive(buffer, buffer.Length, 0);
msg += ASCII.GetString(buffer, 0, bytes);
if(bytes < buffer.Length)
{
break;
}
}
char[] seperator = {'\n'};
string[] msgs = msg.Split(seperator);
if(msg.Length > 2)
{
msg = msgs[msgs.Length-2];
}
else
{
msg = msgs[0];
}
if(!msg.Substring(3,1).Equals(" "))
{
return readLine();
}
return msg;
}
private void sendCommand(String command)
{
Byte[] cmdBytes =
Encoding.ASCII.GetBytes((command+"\r\n").ToCharArray());
clientSocket.Send(cmdBytes, cmdBytes.Length, 0);
readReply();
}
private Socket createDataSocket()
{
sendCommand("PASV");
if(retValue != 227)
{
throw new IOException(reply.Substring(4));
}
int index1 = reply.IndexOf('(');
int index2 = reply.IndexOf(')');
string ipData =
reply.Substring(index1+1,index2-index1-1);
int[] parts = new int[6];
int len = ipData.Length;
int partCount = 0;
string buf="";
for (int i = 0; i < len && partCount <= 6; i++)
{
char ch = Char.Parse(ipData.Substring(i,1));
if (Char.IsDigit(ch))
buf+=ch;
else if (ch != ',')
{
throw new IOException("Malformed PASV reply: " +
reply);
}
if (ch == ',' || i+1 == len)
{
try
{
parts[partCount++] = Int32.Parse(buf);
buf="";
}
catch (Exception)
{
throw new IOException("Malformed PASV reply: " +
reply);
}
}
}
string ipAddress = parts[0] + "."+ parts[1]+ "." +
parts[2] + "." + parts[3];
int port = (parts[4] << 8) + parts[5];
Socket s = new
Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
IPEndPoint ep = new
IPEndPoint(Dns.Resolve(ipAddress).AddressList[0], port);
try
{
s.Connect(ep);
}
catch(Exception)
{
throw new IOException("Can't connect to remote server");
}
return s;
}
}
public class UploadStatusPage : Server.Timer
{
public static void Initialize()
{
FTP gettime = new FTP();
double start = gettime.starttime;
double delay = gettime.delaytime;
new UploadStatusPage(start, delay).Start();
}
public UploadStatusPage(double start, double delay) : base( TimeSpan.FromSeconds( start ), TimeSpan.FromSeconds( delay ) )
{
}
protected override void OnTick()
{
try {
Console.WriteLine("Starting...");
FTP f = new FTP();
f.login();
f.setBinaryMode(true);
f.Thread_Upload(f.localpath,false);
//f.close();
}
catch(Exception e)
{
Console.WriteLine("Caught Error :"+e.Message);
}
}
}
}