//--------------------------------------------------------------------------- // Process each charcter received to do minimal line editing void __fastcall TClientForm::ProcessChar(char Ch) { if (Ch == '\b') { if (FCommand.Length() > 0) { FCommand.SetLength(FCommand.Length() - 1); Socket->SendStr(RawByteString("\b \b")); } else Socket->SendStr(RawByteString('\a')); return; } else if ((Ch == '\n') && FRcvdCR) { // Ignore LF just after CR (CR/LF is normal end of line) FRcvdCR = FALSE; return; } else if (Ch == '\r') { FRcvdCR = TRUE; CommandInterpreter(); return; } else if (Ch == '\n') { CommandInterpreter(); return; } // Ordinary character, put in buffer in some place left FCommand = FCommand + Ch; // Echo to client Socket->Send(&Ch, 1); }
//--------------------------------------------------------------------------- // This is the command line interpreter. Should extend the code to support // every command needed... void __fastcall TClientForm::CommandInterpreter() { // Process Command Socket->SendStr(RawByteString("\r\nExecuting command '" + FCommand + "'...\r\n")); FCommand = FCommand.UpperCase(); if (FCommand == "EXIT") DisconnectButtonClick(this); else if (FCommand == "HELP") Socket->SendStr(RawByteString( "List of commands:\r\n" " Exit logoff from server\r\n" " Help show this help screen\r\n")); else Socket->SendStr(RawByteString("Unknown command, ignoring")); Socket->SendStr(RawByteString("\r\n--> ")); FCommand = ""; }
RawByteString TConfiguration::EncryptPassword(const UnicodeString & Password, const UnicodeString & Key) { if (Password.IsEmpty()) { return RawByteString(); } else { return ::EncryptPassword(Password, Key); } }
RawByteString THierarchicalStorage::ReadStringAsBinaryData(const UnicodeString & Name, const RawByteString & Default) const { UnicodeString UnicodeDefault = AnsiToString(Default); // This should be exactly the same operation as calling ReadString in // C++Builder 6 (non-Unicode) on Unicode-based OS // (conversion is done by Ansi layer of the OS) UnicodeString String = ReadString(Name, UnicodeDefault); AnsiString Ansi = AnsiString(String); RawByteString Result = RawByteString(Ansi.c_str(), Ansi.Length()); return Result; }
//--------------------------------------------------------------------------- RawByteString __fastcall TConfiguration::EncryptPassword(UnicodeString Password, UnicodeString Key) { if (Password.IsEmpty()) { return RawByteString(); } else { return ::EncryptPassword(Password, Key); } }
UnicodeString MungeStr(const UnicodeString & Str, bool ForceAnsi) { RawByteString Source; if (ForceAnsi) { Source = RawByteString(AnsiString(Str)); } else { Source = RawByteString(UTF8String(Str)); if (Source.Length() > Str.Length()) { Source.Insert(CONST_BOM, 1); } } // should contain ASCII characters only RawByteString Dest; char * Buffer = Dest.SetLength(Source.Length() * 3 + 1); putty_mungestr(Source.c_str(), Buffer); PackStr(Dest); return UnicodeString(Dest.c_str(), Dest.Length()); }
//--------------------------------------------------------------------------- // This event handler is called when the client has sent some data to the // server. It is here that we must place the client requests execution // probably by assembling data in lines, parsing those lines for commands // and executing the commands. Here for simplicity, we just echo back the // data sent by the user, without doing anything serious. // To demonstrate that blocking a thread do not block the others, when a '*' // is received, we go to Sleep for a few seconds, effectively blocking the // the client. But as we are multi-threaded, this do not block any other // client. // Do not forget to call the Synchronize method if you need to update the // user interface. Only the main thread can do it (VCL is not thread safe). void __fastcall TClientThread::ServerWSocketDataAvailable(TObject *Sender, WORD Error) { char Buffer[4096]; int Count; // Receive as much data as possible Count = FClientSocket->Receive(&Buffer, sizeof(Buffer)); // If data received, then process it if (Count > 0) { if (Buffer[0] == '*') { // If the first character is '*' then go to sleep a while FClientSocket->SendStr(RawByteString("Sleeping for 15 sec...\r\n")); Sleep(15000); FClientSocket->SendStr(RawByteString("Wake up !\r\n")); } else // Just echo data back to client FClientSocket->Send(&Buffer, Count); } }
//--------------------------------------------------------------------------- // This is the main thread routine. There is not much to do because TWSocket // is event drive. So everythong to do is done inside an event handler, // mostly the OnDataAvailable event handler which is triggered each time // the client send something to the server. void __fastcall TClientThread::Execute() { // Create the client TWSocket. It is important to create it inside the // Execute method because it *must* be created by the thread. Otherwise // the messages sent by winsock would be processed in the main thread // context, effectively disabling multi-threading. FClientSocket = new TWSocket(NULL); FClientSocket->MultiThreaded = true; FClientSocket->HSocket = FClientHSocket; FClientSocket->OnDataAvailable = ServerWSocketDataAvailable; FClientSocket->OnSessionClosed = ServerWSocketSessionClosed; // Send the welcome message FClientSocket->SendStr(RawByteString("Hello !\r\n >")); // Message loop to handle TWSocket messages // The loop is exited when WM_QUIT message is received FClientSocket->MessageLoop(); // Returning from the Execute function effectively terminate the thread }
RawByteString __fastcall RawByteString::operator +(const RawByteString & rhs) const { rawstring_t Result = Data + rhs.Data; return RawByteString(reinterpret_cast<const char *>(Result.c_str()), static_cast<int>(Result.size())); }
int GetUserpassInput(prompts_t * p, const uint8_t * /*in*/, int /*inlen*/) { DebugAssert(p != nullptr); TSecureShell * SecureShell = NB_STATIC_DOWNCAST(TSecureShell, p->frontend); DebugAssert(SecureShell != nullptr); int Result; std::unique_ptr<TStrings> Prompts(new TStringList()); std::unique_ptr<TStrings> Results(new TStringList()); { UnicodeString Name = UTF8ToString(p->name); UnicodeString AName = Name; TPromptKind PromptKind = SecureShell->IdentifyPromptKind(AName); bool UTF8Prompt = (PromptKind != pkPassphrase); for (size_t Index = 0; Index < p->n_prompts; ++Index) { prompt_t * Prompt = p->prompts[Index]; UnicodeString S; if (UTF8Prompt) { S = UTF8ToString(Prompt->prompt); } else { S = UnicodeString(AnsiString(Prompt->prompt)); } Prompts->AddObject(S, reinterpret_cast<TObject *>(static_cast<size_t>(FLAGMASK(Prompt->echo, pupEcho)))); // this fails, when new passwords do not match on change password prompt, // and putty retries the prompt DebugAssert(Prompt->resultsize == 0); Results->Add(L""); } UnicodeString Instructions = UTF8ToString(p->instruction); if (SecureShell->PromptUser(p->to_server != 0, Name, p->name_reqd != 0, Instructions, p->instr_reqd != 0, Prompts.get(), Results.get())) { for (size_t Index = 0; Index < p->n_prompts; ++Index) { prompt_t * Prompt = p->prompts[Index]; RawByteString S; if (UTF8Prompt) { S = RawByteString(UTF8String(Results->GetString(Index))); } else { S = RawByteString(AnsiString(Results->GetString(Index))); } prompt_set_result(Prompt, S.c_str()); } Result = 1; } else { Result = 0; } } __finally { // delete Prompts; // delete Results; }; return Result; }