/// <summary> /// Handle commands at the Read level /// </summary> /// <param name="buffer">Line buffer</param> /// <param name="parser">Parser</param> private bool ReadCommand(LineBuffer buffer, Parser parser) { switch (parser.NextCommand()) { case Parser.ParseToken.COMMENT: CommentCommand(buffer, parser); break; case Parser.ParseToken.SAY: SayCommand(buffer); break; case Parser.ParseToken.OPTION: ChangeState(CoSyState.OPT); OptionCommand(parser); break; case Parser.ParseToken.JOIN: JoinCommand(buffer, parser); break; case Parser.ParseToken.RESIGN: ResignCommand(buffer, parser); break; case Parser.ParseToken.KILLSCRATCH: _scratch.Clear(); buffer.WriteLine("Scratchpad Deleted"); break; case Parser.ParseToken.BYE: return ByeCommand(buffer, parser); case Parser.ParseToken.QUIT: QuitState(); break; } return false; }
/// <summary> /// Handle the JOIN command. /// </summary> /// <param name="buffer">Line buffer</param> /// <param name="parser">Parser</param> private void JoinCommand(LineBuffer buffer, Parser parser) { string forumName = parser.NextArgument(); if (!string.IsNullOrEmpty(forumName)) { string topicName = null; string[] joinParams = forumName.Split(new[] {'/'}); if (joinParams.Length == 2) { forumName = joinParams[0]; topicName = joinParams[1]; } if (!_forums.IsJoined(forumName)) { buffer.WriteString(string.Format("You are not registered in '{0}'. ", forumName)); if (Ask(buffer, "Would you like to register (y/n)? ")) { if (!_forums.Join(forumName)) { buffer.WriteRedirectableLine(string.Format("No conference '{0}'.", forumName)); return; } } } Forum thisForum = _forums[forumName]; Topic thisTopic; do { if (topicName != null && !thisForum.Topics.Contains(topicName)) { buffer.WriteLine("Couldn't find topic: No such file or directory"); buffer.WriteLine(string.Format("Topic '{0}' not found.", topicName)); topicName = thisForum.Topics[0].Name; } if (topicName == null) { buffer.WriteString("Topics are:"); for (int c = 0; c < thisForum.Topics.Count; ++c) { string topicString = thisForum.Topics[c].Name; if (c > 0) { buffer.WriteString(","); } buffer.WriteString(string.Format(" '{0}'", topicString)); } buffer.WriteLine(""); buffer.WriteString("Topic? "); topicName = buffer.ReadLine(); if (topicName == "quit") { return; } } thisTopic = thisForum.Topics[topicName]; } while (thisTopic == null); buffer.WriteRedirectableLine(string.Format("Joining conference '{0}', topic '{1}'. {2} new message(s).", forumName, topicName, thisTopic.Unread)); _currentTopic = thisTopic; ChangeState(CoSyState.READ); } }
/// <summary> /// Handle commands at the main level. /// </summary> /// <param name="buffer">Line buffer</param> /// <param name="parser">The command parser</param> private bool MainCommand(LineBuffer buffer, Parser parser) { Parser.ParseToken nextCommand = parser.NextCommand(); if (nextCommand == Parser.ParseToken.FILE) { buffer.Output = _scratch; nextCommand = parser.NextCommand(); } switch (nextCommand) { case Parser.ParseToken.DOWNLOAD: DownloadCommand(buffer); break; case Parser.ParseToken.UPLOAD: UploadCommand(buffer); break; case Parser.ParseToken.OPTION: ChangeState(CoSyState.OPT); OptionCommand(parser); break; case Parser.ParseToken.SCPUT: ScputCommand(parser); break; case Parser.ParseToken.SCRIPT: buffer.Script = _script; break; case Parser.ParseToken.JOIN: JoinCommand(buffer, parser); break; case Parser.ParseToken.RESIGN: ResignCommand(buffer, parser); break; case Parser.ParseToken.READ: if (parser.NextArgument() == "all") { buffer.WriteLine("......"); ReadScratchpad(buffer); buffer.WriteLine(""); ShowScratchpadSize(buffer); } break; case Parser.ParseToken.KILLSCRATCH: _scratch.Clear(); buffer.WriteLine("Scratchpad Deleted"); break; case Parser.ParseToken.BYE: return ByeCommand(buffer, parser); } return false; }
/// <summary> /// Handle the JOIN command. /// </summary> /// <param name="buffer">Line buffer</param> /// <param name="parser">Parser</param> private void JoinCommand(LineBuffer buffer, Parser parser) { string forumName = parser.NextArgument(); if (!string.IsNullOrEmpty(forumName)) { string topicName = null; string[] joinParams = forumName.Split(new[] { '/' }); if (joinParams.Length == 2) { forumName = joinParams[0]; topicName = joinParams[1]; } if (!_forums.IsJoined(forumName)) { buffer.WriteString(string.Format("You are not registered in '{0}'. ", forumName)); if (Ask(buffer, "Would you like to register (y/n)? ")) { if (!_forums.Join(forumName)) { buffer.WriteRedirectableLine(string.Format("No conference '{0}'.", forumName)); return; } } } Forum thisForum = _forums[forumName]; Topic thisTopic; do { if (topicName != null && !thisForum.Topics.Contains(topicName)) { buffer.WriteLine("Couldn't find topic: No such file or directory"); buffer.WriteLine(string.Format("Topic '{0}' not found.", topicName)); topicName = thisForum.Topics[0].Name; } if (topicName == null) { buffer.WriteString("Topics are:"); for (int c = 0; c < thisForum.Topics.Count; ++c) { string topicString = thisForum.Topics[c].Name; if (c > 0) { buffer.WriteString(","); } buffer.WriteString(string.Format(" '{0}'", topicString)); } buffer.WriteLine(""); buffer.WriteString("Topic? "); topicName = buffer.ReadLine(); if (topicName == "quit") { return; } } thisTopic = thisForum.Topics[topicName]; } while (thisTopic == null); buffer.WriteRedirectableLine(string.Format("Joining conference '{0}', topic '{1}'. {2} new message(s).", forumName, topicName, thisTopic.Unread)); _currentTopic = thisTopic; ChangeState(CoSyState.READ); } }
/// <summary> /// This is the main CoSy client communication thread. /// </summary> /// <param name="client">The handle of the TCP client connection</param> private void HandleClientComm(object client) { TcpClient tcpClient = (TcpClient)client; TelnetStream stream = new TelnetStream(tcpClient.GetStream()); LineBuffer buffer = new LineBuffer(stream); try { DateTime loginTime = DateTime.Now; buffer.WriteLine("CIX Conferencing System"); while (true) { buffer.WriteString("login: "******"qix" || loginString == "cix") { break; } buffer.WriteLine("Unknown login"); } Version ver = Assembly.GetEntryAssembly().GetName().Version; string versionString = string.Format("{0}.{1}.{2}", ver.Major, ver.Minor, ver.Build); buffer.WriteLine(string.Format("{0} {1}", Properties.Resources.CIXAPIProxyTitle, versionString)); buffer.WriteString("Nickname? (Enter 'new' for new user) "); string userName = buffer.ReadLine(); buffer.WriteString("Password: "******""); Console.WriteLine("Logged in as '{0}' with password '{1}'", userName, password); _forums = new Forums(); buffer.WriteLine(string.Format("You are a member of {0} conference(s).", _forums.Count)); buffer.WriteLine("Max scratchsize during file has been set to 20000000 bytes"); TopLevelCommand(buffer); buffer.Output = null; // Round up login time to 1 minute. TimeSpan onlineTime = (DateTime.Now - loginTime).Add(new TimeSpan(0, 1, 0)); buffer.WriteLine(string.Format("{0}, you have been online {1}:{2} on line 5", userName, onlineTime.Hours, onlineTime.Minutes)); buffer.WriteLine("Goodbye from CIX !!!HANGUP NOW!!!"); } catch (IOException) { Console.WriteLine("Client terminated connection"); } catch (IndexOutOfRangeException) { Console.WriteLine("Client terminated connection"); } catch (AuthenticationException) { // Authentication failed. Likely the app has been revoked. Clear // the tokens and force re-authentication. Properties.Settings.Default.oauthToken = ""; Properties.Settings.Default.oauthTokenSecret = ""; Properties.Settings.Default.Save(); } tcpClient.Close(); }
/// <summary> /// Handle a SAY or COMMENT in a forum topic. The current topic must be set before this /// function is called or it does nothing. The replyNumber specifies whether this is a new /// thread (a SAY) or a reply to an existing thread (a COMMENT). A value of 0 starts a new /// thread otherwise it is the number of the message to which this is a reply. /// </summary> /// <param name="buffer">The I/O buffer</param> /// <param name="replyNumber">The message to which this is a reply</param> private void SayOrCommentCommand(LineBuffer buffer, int replyNumber) { if (_currentTopic != null) { PostMessage message = new PostMessage { MsgID = replyNumber, Forum = _currentTopic.Forum.Name, Topic = _currentTopic.Name }; buffer.WriteLine("Enter message. End with '.<CR>'"); // The body of the message comprises multiple lines terminated by a line // that contains a single period character and nothing else. StringBuilder bodyMessage = new StringBuilder(); string bodyLine = buffer.ReadLine(); while (bodyLine != ".") { bodyMessage.AppendLine(bodyLine.Trim()); bodyLine = buffer.ReadLine(); } message.Body = bodyMessage.ToString(); StringBuilder postMessageXml = new StringBuilder(); using (XmlWriter writer = XmlWriter.Create(postMessageXml)) { XmlSerializer serializer = new XmlSerializer(typeof (PostMessage)); serializer.Serialize(writer, message); } // Remove the header postMessageXml.Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", ""); // Messages are posted as 7-bit ASCII. UTF8Encoding encoder = new UTF8Encoding(); byte[] postMessageBytes = encoder.GetBytes(postMessageXml.ToString()); WebRequest wrPosturl = WebRequest.Create(CIXOAuth.PostUri(CoSyServer.CIXAPIServer + "cix.svc/forums/post.xml")); wrPosturl.Method = "POST"; wrPosturl.ContentLength = encoder.GetByteCount(postMessageXml.ToString()); wrPosturl.ContentType = "application/xml"; Stream dataStream = wrPosturl.GetRequestStream(); dataStream.Write(postMessageBytes, 0, postMessageBytes.Length); dataStream.Close(); buffer.WriteString("Adding.."); try { Stream objStream = wrPosturl.GetResponse().GetResponseStream(); if (objStream != null) { using (TextReader reader = new StreamReader(objStream)) { XmlDocument doc = new XmlDocument {InnerXml = reader.ReadLine()}; if (doc.DocumentElement != null) { int newMessageNumber = Int32.Parse(doc.DocumentElement.InnerText); buffer.WriteLine(string.Format("Message {0} added.", newMessageNumber)); } } } } catch (WebException e) { if (e.Message.Contains("401")) { throw new AuthenticationException("Authentication Failed", e); } } } }
/// <summary> /// Handle the top-level Main commands. /// </summary> /// <param name="buffer">The telnet input stream</param> private void TopLevelCommand(LineBuffer buffer) { ChangeState(CoSyState.MAIN); do { if (!buffer.IsRunningScript) { buffer.Output = null; buffer.WriteString(PromptForState()); } } while (!_endThread && !ActionCommand(buffer, buffer.ReadLine())); }
/// <summary> /// Read all unread messages into the scratchpad. /// </summary> /// <param name="buffer">The I/O buffer</param> private static void ReadScratchpad(LineBuffer buffer) { WebRequest wrGeturl = WebRequest.Create(CIXOAuth.GetUri("cix.svc/user/cixtelnetd/65535/0/scratchpad.xml")); wrGeturl.Method = "GET"; try { Stream objStream = wrGeturl.GetResponse().GetResponseStream(); if (objStream != null) { using (XmlReader reader = XmlReader.Create(objStream)) { XmlSerializer serializer = new XmlSerializer(typeof(Scratchpad)); Scratchpad scratchpad = (Scratchpad)serializer.Deserialize(reader); buffer.WriteRedirectableLine("Checking for conference activity."); Dictionary<string, List<ScratchpadMessagesMsg> > allMessages = new Dictionary<string, List<ScratchpadMessagesMsg> >(); foreach (ScratchpadMessagesMsg message in scratchpad.Messages) { string thisTopic = string.Format("{0}/{1}", message.Forum, message.Topic); List<ScratchpadMessagesMsg> topicList; if (!allMessages.TryGetValue(thisTopic, out topicList)) { topicList = new List<ScratchpadMessagesMsg>(); allMessages[thisTopic] = topicList; } topicList.Add(message); } foreach (string thisTopic in allMessages.Keys) { List<ScratchpadMessagesMsg> topicList = allMessages[thisTopic]; buffer.WriteRedirectableLine(string.Format("Joining {0} {1} new message(s).", thisTopic, topicList.Count)); foreach (ScratchpadMessagesMsg message in topicList) { string [] monthString = new[] { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"}; StringBuilder messageHeader = new StringBuilder(); messageHeader.AppendFormat(">>>{0} {1} {2}({3})", thisTopic, message.ID, message.Author, message.Body.Length); DateTime messageDate = DateTime.Parse(message.DateTime); messageHeader.AppendFormat("{0}{1}{2} ", messageDate.Day, monthString[messageDate.Month - 1], messageDate.Year - 2000); messageHeader.AppendFormat("{0}:{1}", messageDate.Hour, messageDate.Minute); if (message.ReplyTo != "0") { messageHeader.AppendFormat(" c{0}", message.ReplyTo); } buffer.WriteRedirectableLine(messageHeader.ToString()); buffer.WriteRedirectableLine(message.Body); } } buffer.WriteRedirectableLine("No unread messages"); } } } catch (WebException e) { if (e.Message.Contains("401")) { throw new AuthenticationException("Authentication Failed", e); } } }
/// <summary> /// Direct the specified input to the appropriate command handler depending /// on the state which we're in. /// </summary> /// <param name="buffer">The I/O buffer</param> /// <param name="command">The command string</param> /// <returns>Return true if the command was a BYE</returns> private bool ActionCommand(LineBuffer buffer, string command) { Parser parser = new Parser(command); bool isBye = false; switch (CurrentState) { case CoSyState.MAIN: isBye = MainCommand(buffer, parser); break; case CoSyState.OPT: isBye = OptionCommand(parser); break; case CoSyState.READ: isBye = ReadCommand(buffer, parser); break; } return isBye; }
/// <summary> /// This is the main CoSy client communication thread. /// </summary> /// <param name="client">The handle of the TCP client connection</param> private void HandleClientComm(object client) { TcpClient tcpClient = (TcpClient)client; TelnetStream stream = new TelnetStream(tcpClient.GetStream()); LineBuffer buffer = new LineBuffer(stream); try { DateTime loginTime = DateTime.Now; buffer.WriteLine("CIX Conferencing System"); while (true) { buffer.WriteString("login: "******"qix" || loginString == "cix") { break; } buffer.WriteLine("Unknown login"); } Version ver = Assembly.GetEntryAssembly().GetName().Version; string versionString = string.Format("{0}.{1}.{2}", ver.Major, ver.Minor, ver.Build); buffer.WriteLine(string.Format("CIX API Proxy {0}", versionString)); buffer.WriteString("Nickname? (Enter 'new' for new user) "); string userName = buffer.ReadLine(); buffer.WriteString("Password: "******""); Console.WriteLine("Logged in as '{0}' with password '{1}'", userName, password); APIRequest.Username = userName; APIRequest.Password = password; LoadScratchpad(); _forums = new Forums(); buffer.WriteLine(string.Format("You are a member of {0} conference(s).", _forums.Count)); buffer.WriteLine("Max scratchsize during file has been set to 20000000 bytes"); TopLevelCommand(buffer); buffer.Output = null; // Round up login time to 1 minute. TimeSpan onlineTime = (DateTime.Now - loginTime).Add(new TimeSpan(0, 1, 0)); buffer.WriteLine(string.Format("{0}, you have been online {1}:{2} on line 5", userName, onlineTime.Hours, onlineTime.Minutes)); buffer.WriteLine("Goodbye from CIX !!!HANGUP NOW!!!"); } catch (IOException) { Console.WriteLine("Client terminated connection"); } catch (IndexOutOfRangeException) { Console.WriteLine("Client terminated connection"); } catch (AuthenticationException) { Console.WriteLine("Client not authorised"); } tcpClient.Close(); }
/// <summary> /// Display a prompt and request a Yes or No response. /// </summary> /// <param name="buffer">Line buffer</param> /// <param name="prompt">The prompt string</param> /// <returns>True if the user responded Yes, false if anything else</returns> private static bool Ask(LineBuffer buffer, string prompt) { while (true) { buffer.WriteString(prompt); buffer.WriteString("Y\b"); string yesNo = buffer.ReadLine(); if (string.IsNullOrEmpty(yesNo)) { continue; } if (yesNo.ToUpper().StartsWith("Y")) { return true; } if (yesNo.ToUpper().StartsWith("N")) { return false; } } }
/// <summary> /// Read all unread messages into the scratchpad. /// </summary> /// <param name="buffer">The I/O buffer</param> private static void ReadScratchpad(LineBuffer buffer) { WebRequest wrGeturl = APIRequest.Get("user/cixtelnetd/65535/0/scratchpad", APIRequest.APIFormat.XML); try { Stream objStream = wrGeturl.GetResponse().GetResponseStream(); if (objStream != null) { using (XmlReader reader = XmlReader.Create(objStream)) { XmlSerializer serializer = new XmlSerializer(typeof(Scratchpad)); Scratchpad scratchpad = (Scratchpad)serializer.Deserialize(reader); buffer.WriteRedirectableLine("Checking for conference activity."); Dictionary <string, List <ScratchpadMessagesMsg> > allMessages = new Dictionary <string, List <ScratchpadMessagesMsg> >(); foreach (ScratchpadMessagesMsg message in scratchpad.Messages) { string thisTopic = string.Format("{0}/{1}", message.Forum, message.Topic); List <ScratchpadMessagesMsg> topicList; if (!allMessages.TryGetValue(thisTopic, out topicList)) { topicList = new List <ScratchpadMessagesMsg>(); allMessages[thisTopic] = topicList; } topicList.Add(message); } foreach (string thisTopic in allMessages.Keys) { List <ScratchpadMessagesMsg> topicList = allMessages[thisTopic]; buffer.WriteRedirectableLine(string.Format("Joining {0} {1} new message(s).", thisTopic, topicList.Count)); foreach (ScratchpadMessagesMsg message in topicList) { string [] monthString = { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" }; StringBuilder messageHeader = new StringBuilder(); messageHeader.AppendFormat(">>>{0} {1} {2}({3})", thisTopic, message.ID, message.Author, message.Body.Length); DateTime messageDate = DateTime.Parse(message.DateTime); messageHeader.AppendFormat("{0}{1}{2} ", messageDate.Day, monthString[messageDate.Month - 1], messageDate.Year - 2000); messageHeader.AppendFormat("{0}:{1}", messageDate.Hour, messageDate.Minute); if (message.ReplyTo != "0") { messageHeader.AppendFormat(" c{0}", message.ReplyTo); } buffer.WriteRedirectableLine(messageHeader.ToString()); buffer.WriteRedirectableLine(message.Body); } } buffer.WriteRedirectableLine("No unread messages"); } } } catch (WebException e) { if (e.Message.Contains("401")) { throw new AuthenticationException("Authentication Failed", e); } } }
/// <summary> /// Show the current scratchpad size in bytes. Messages from the CIX API are reformatted into /// CoSy scratchpad format messages. /// </summary> /// <param name="buffer">The output buffer</param> private void ShowScratchpadSize(LineBuffer buffer) { buffer.WriteLine(string.Format("Scratchpad is {0} bytes.", _scratch.Length)); }
/// <summary> /// Start a new message in the specified topic. The message body follows /// in the input stream. /// </summary> /// <param name="buffer">Input stream</param> private void SayCommand(LineBuffer buffer) { SayOrCommentCommand(buffer, 0); }
/// <summary> /// Handle the RESIGN command. /// /// CAUTION: The API currently doesn't support resigning topics within a forum, although /// the web service apparently seems to. Until this is supported, the resign command will /// resign entire forums. For safety, if a topic name is specified in the argument we /// bail out and do nothing. /// </summary> /// <param name="buffer">Input buffer</param> /// <param name="parser">Parser</param> private void ResignCommand(LineBuffer buffer, Parser parser) { string forumName = parser.NextArgument(); if (string.IsNullOrEmpty(forumName)) { if (_currentTopic == null) { buffer.WriteString("Conference name? "); forumName = buffer.ReadLine(); } else { forumName = _currentTopic.Forum.Name; } } else { string[] joinParams = forumName.Split(new[] {'/'}); if (joinParams.Length == 2) { return; // Bail out if a topic name was specified. } } if (!_forums.IsJoined(forumName)) { buffer.WriteLine(string.Format("You are not a member of conference '{0}'.", forumName)); return; } buffer.WriteLine(string.Format("Resigning from conference '{0}'.", forumName)); _forums.Resign(forumName); ChangeState(CoSyState.MAIN); }
/// <summary> /// Handle the BYE command. /// </summary> /// <param name="buffer">Line buffer</param> /// <param name="parser">Parser</param> private bool ByeCommand(LineBuffer buffer, Parser parser) { if (parser.NextArgument() != "y" && _scratch.Length > 0) { buffer.WriteString("OK to delete your scratchpad? (y/n/q)? "); string yesNoQuit = buffer.ReadLine(); if (yesNoQuit == "q") { return false; } } return true; }
/// <summary> /// Comment to an existing message in the specified topic. The message body /// follows in the input stream. The command array contains the argument to the /// comment command. /// </summary> /// <param name="buffer">Input stream</param> /// <param name="parser">Buffer</param> private void CommentCommand(LineBuffer buffer, Parser parser) { if (_currentTopic != null) { int replyNumber = _currentTopic.MessageID; string commentArgument = parser.NextArgument(); if (commentArgument != "") { if (!Int32.TryParse(commentArgument, out replyNumber)) { buffer.WriteLine("Invalid comment number"); return; } } SayOrCommentCommand(buffer, replyNumber); } }
/// <summary> /// Do a ZModem download of the scratchpad and optionally delete the scratchpad /// after a successful completion. /// </summary> /// <param name="buffer">Output buffer</param> private void DownloadCommand(LineBuffer buffer) { buffer.WriteLine("Zmodem download started... (to abort ^X^X^X^X^X)"); buffer.WriteLine(string.Format("Filesize {0} bytes, estimated time at 2880 cps : 1 sec", _scratch.Length)); string scratchFileName = Path.GetTempFileName(); using (FileStream fileStream = new FileStream(scratchFileName, FileMode.Create)) { ASCIIEncoding encoder = new ASCIIEncoding(); byte[] rawScratchpad = encoder.GetBytes(_scratch.ToString()); fileStream.Write(rawScratchpad, 0, rawScratchpad.Length); } ZModem.ZModem zModem = new ZModem.ZModem(buffer.Stream) {Filename = scratchFileName}; bool success = zModem.Send(); buffer.WriteLine(success ? "Download succeeded" : "Download failed"); if (success) { buffer.WriteString("OK to delete the downloaded scratchpad-file? (y/n)? N\b"); string yesNoResponse = buffer.ReadLine(); if (yesNoResponse.Trim() == "Y") { _scratch.Clear(); } } File.Delete(scratchFileName); }
/// <summary> /// Do a ZModem upload into the scratchpad then show the scratchpad size afterwards. /// </summary> /// <param name="buffer">The I/O buffer</param> private void UploadCommand(LineBuffer buffer) { buffer.WriteLine("Zmodem upload (to abort ^X^X^X^X^X)"); string scratchFileName = Path.GetTempFileName(); ZModem.ZModem zModem = new ZModem.ZModem(buffer.Stream) { Filename = scratchFileName }; bool success = zModem.Receive(); buffer.WriteLine(success ? "Upload succeeded" : "Upload failed"); _scratch.Clear(); if (success) { using (FileStream fileStream = new FileStream(scratchFileName, FileMode.Open)) { byte[] rawScratchpad = new byte[fileStream.Length]; fileStream.Read(rawScratchpad, 0, (int)fileStream.Length); _scratch.Append(new StringBuilder(Encoding.ASCII.GetString(rawScratchpad))); } File.Delete(scratchFileName); } ShowScratchpadSize(buffer); }
/// <summary> /// Handle commands at the main level. /// </summary> /// <param name="buffer">Line buffer</param> /// <param name="parser">The command parser</param> private bool MainCommand(LineBuffer buffer, Parser parser) { Parser.ParseToken nextCommand = parser.NextCommand(); if (nextCommand == Parser.ParseToken.FILE) { buffer.Output = _scratch; nextCommand = parser.NextCommand(); } switch (nextCommand) { case Parser.ParseToken.DOWNLOAD: DownloadCommand(buffer); break; case Parser.ParseToken.UPLOAD: UploadCommand(buffer); break; case Parser.ParseToken.OPTION: ChangeState(CoSyState.OPT); OptionCommand(parser); break; case Parser.ParseToken.SCPUT: ScputCommand(parser); break; case Parser.ParseToken.SCRIPT: buffer.Script = _script; break; case Parser.ParseToken.JOIN: JoinCommand(buffer, parser); break; case Parser.ParseToken.RESIGN: ResignCommand(buffer, parser); break; case Parser.ParseToken.READ: if (parser.NextArgument() == "all") { buffer.WriteLine("......"); ReadScratchpad(buffer); buffer.WriteLine(""); ShowScratchpadSize(buffer); } break; case Parser.ParseToken.KILLSCRATCH: _scratch.Clear(); buffer.WriteLine("Scratchpad Deleted"); break; case Parser.ParseToken.BYE: return(ByeCommand(buffer, parser)); } return(false); }