Sending unicode command with TIdCmdTCPClient - delphi

I`m using Delphi XE6 and Indy 10
I want to send an Unicode String as Command to a TIdCMDTCPServer from a TIdCMDTCPClient
I`m sending command with SendCMD method of IdCMDTCPClient component but received command shown as ' ? ' Character !
In fact I have a Command (for example : "USER_REG") and some parameters with that and Parameters are an Unicode String ( Persian characters )
I have set encoding of command to IndyTextEncoding_UTF8 or Encode command with UTF8Encode function but there is no chance !
Example of Command :
CMD := 'USER_REG#register_user(' + QuotedStr('محمود مهری') + ')';
TCPClient.SendCmd(CMD, -1, IndyTextEncoding_UTF8);
or
TCPClient.SendCmd(UTF8Encode(CMD), -1, IndyTextEncoding_UTF8);
How can I send Unicode Strings as Command ?
thanks ...

TIdCmdTCPServer and TIdCmdTCPClient are not designed to be used together. If you are using TIdCmdTCPServer, you should be using TIdTCPClient instead. If you want to use TIdCmdTCPClient, then at the very least DO NOT use its SendCmd() or GetResponse() methods. TIdCmdTCPClient uses an internal reading thread to receive messages from the server. That thread will interfere with GetResponse()'s reading (SendCmd() calls GetResponse() internally). Use the client's IOHandler.WriteLn() method instead, and then let the TIdCmdTCPClient.CommandHandlers read the server's response.
That being said, specifying IndyTextEncoding_UTF8 on the actual send is the correct thing to do. You can alternatively set the client's IOHandler.DefStringEncoding property instead. Either way, using UTF8Encode() in this situation is useless in Delphi 2009+, because SendCmd() (and WriteLn()) takes a UnicodeString as input, so the UTF-8 encoded RawByteString that UTF8Encode() returns will get converted by the RTL back to a UTF-16 UnicodeString, which IndyTextEncoding_UTF8 will then re-encode back to UTF-8 again during transmission. That is useless overhead.
On the server side, you need to use IndyTextEncoding_UTF8 on the reads so the incoming UTF-8 encoded commands will be decoded correctly. Since TIdCmdTCPServer is doing the actual reading for you, you will have to assign IndyTextEncoding_UTF8 to the AContext.Connection.IOHandler.DefStringEncoding property in the OnConnect event. Otherwise, Indy's default encoding will be used instead, and that encoding is US-ASCII by default (configurable via the IdGlobal.GIdDefaultTextEncoding variable). That is why you are seeing the client's non-ASCII characters being converted to ? characters. US-ASCII does not supports characters above #127.

Related

How to execute a stored procedure with date in adsweb

I'm trying to execute a stored procedure in a http call to adsweb. The procedure calls for a date and a string.
if i enter:
GetBalance?todate='2018-03-15'&phone='9999999'
I get a:
Error 7200: AQE Error: State = 07006; NativeError = 2109; [iAnywhere Solutions][Advantage SQL Engine]Conversion error
How would I enter the date?
It works fine in Arc32
Thanks,
Kim
I've done this a lot in the past so I know it works. Usually problems are due to special characters in the URI. First of all, don't include any actual quote characters in the URI string like you have in your example.
For example the URI would just be:
GetBalance?todate=2018-03-15&phone=9999999
The adsweb module parser will split the procedure arguments on the & character so you don't need to use quotes.
Also if you have parameter data with special characters like quotes or percents, you need to encode them prior to sending and the module will decode them for you. I use encodeURIComponent in javascript to encode them.

IdWhois result with Unicode characters

I'm using IdWhois to work with the RFC954 protocol.
When the result contains Unicode characters like "é, ó, ç...", I just get a question mark "�" instead of the char. I usually have difficulties when need to make string conversion into Delphi. Tried examples found on Google, but no success. So right now I'm thinking maybe the protocol works only with ASCII chars? No idea.
Original code, without any try of conversion (none of them worked anyway), running on Delphi 10 Seattle:
var
Whois: TIdWhois;
RequestResult: String;
begin
Whois:= TIdWhois.Create(Nil);
Whois.ReadTimeout:= 10000;
Whois.ConnectTimeout:= 10000;
try
Whois.Host:= WhoisServer;
try
RequestResult:= Whois.WhoIs(URL);
...
If I add RequestResult to a Memo, or while debugging, I just get the question mark instead of the Unicode characters.

Encrypt String with 3DES usingDelphi 10.1 Berlin

I need to encrypt an 10-byte string in Delphi using 3DES.
It must get the same result than this PHP code:
function encrypt_3DES($message, $key){
$bytes = array(0,0,0,0,0,0,0,0);
$iv = implode(array_map("chr", $bytes));
$ciphertext = mcrypt_encrypt(MCRYPT_3DES, $key, $message, MCRYPT_MODE_CBC, $iv);
return $ciphertext;
I have been trying to code it using DCPCrypt and LockBox 3. I have finally discarded DCPCrypt because it hasn't been update lately and I'm not sure if it works correctly with Delphi 10.1 Berlin, so I have focused in LockBox 3, but I haven't been able to get the encryption right.
The encryption key is a 24bytes key (which I have its base64 representation). I can't find how to create such key using the TSymetricKey class of LockBox to pass it to an Codec.Init method. So I put it on an AnsiString and set it on the Password property (although the documentations says that there is a utf8Password but I can't find it).
Then there is a method called EncryptAnsiString, but again it expects strings (utf16 on Delphi 10.1 Berlin) instead of AnsiStrings (although the documentation says the contrary), so I'm not surprised that the result doesn't match what I'm looking for (the same value encrypted on that PHP snippet).
This is my Delphi Code :
function Encrypt(Data: AnsiString; LocalKey: AnsiString): AnsiString;
var
BinaryLocalKey: TBytes;
strLocalKey, strTripleDes: AnsiString;
begin
BinaryLocalKey := DecodeBase64(LocalKey);
setString(strLocalKey, PAnsiChar(#BinaryLocalKey[0]), Length(BinaryLocalKey));
Codec1.Rest;
Codec1.Password := strLocalKey;
Codec1.EncryptAnsiString(Data, strTripleDES);
Codec1.Reset;
Result := strTripleDes;
end;
But this Code not only doesn't get the same result as the PHP code, but at every call it returns a different result for the same input.
NOTE: Codec1 is a component linked to a TCryptographicLibrary component, and with the propertis ChainMode set to CBC* and Cipher set to 3DES (Keying option 1)
Does somebody know how to properly get this 3DES encryption ?.
Thank you.
A random IV is generated for each message. The low 8 bytes of the IV are a nonce and the high bytes are zero. These low 8 bytes are prepended to the output.
If you want to send the IV via a side channel, then strip the first 8 bytes out of the nominal ciphertext.
If you want to control the IV, then use version 3.7.0 (https://github.com/SeanBDurkin/tplockbox). You will need to set the advanced options and implement the OnGetIV method.
The asterisk (*) rendered in the property editors for cipher selection and chain mode selection, mean that this selection is a recommended one.

Default TEncoding.UTF8 discarding invalid blocks of data in TStreamReader input

I'm using a TStreamReader to read data from a file that purports to be utf-8. I have no problem reading the file until it comes to a section containing what appears to me to be a UTF-8 "£" symbol with the preceding xC2 missing - the file only contains the xA3 part of the character. I've traced this through the run-time library until it calls
Result := UnicodeFromLocaleChars(FCodePage, FMBToWCharFlags,
PAnsiChar(Bytes), ByteCount, nil, 0);
which returns 0 indicating that it doesn't like the input. Unfortunately the TStreamReader simply ends up discarding this buffer of input and then continues with the rest of the file without raising an error. This is extremely misleading about what the problem but that is just a side issue.
The issue appears to be a "defect" in the UTF-8 TEncoding class in that it simply discards the results of a failed conversion whilst the TStreamReader assumes that this isn't the behaviour of TEncoding.
I can work around this by using
Reader := TStreamReader.Create(FileStream, TMBCSEncoding.Create(CP_UTF8, 0, 0));
instead of
Reader := TStreamReader.Create(FileStream, TEncoding.UTF8);
as this makes it ignore the corrupt UTF-8 and simply include something (I haven't checked what) in my output. However, I would like to combine allowing the data through with reporting it and there doesn't seem to be any obvious way of doing this as the behaviour is hidden deep within the library.
Does anyone know of any standard Delphi library tools for doing this or do I need to resort to a lot of custom code?

Objective-C Remove ANSI Color Control Codes

I'm building an iOS application that communicates with a remote server. In this case, I'm executing commands using SSH, however, the response coming back from the server is coming in the form of what appears to be hexadecimal. My delegate function for handling responses from a remote server takes the response argument as an NSString, however, this is the content of the string returned (command executed was "ls /" )
ls /\r\n\x1b[0m\x1b[01;34mbin\x1b[0m \x1b[01;34mdev\x1b[0m \x1b[01;36minitrd.img\x1b[0m \x1b[01;34mlib64\x1b[0m \x1b[01;34mmnt\x1b[0m \x1b[01;34mroot\x1b[0m \x1b[01;34msrv\x1b[0m \x1b[01;34musr\x1b[0m\r\n\x1b[01;34mboot\x1b[0m \x1b[01;34metc\x1b[0m \x1b[01;36minitrd.img.old\x1b[0m \x1b[01;34mlost+found\x1b[0m \x1b[01;34mopt\x1b[0m \x1b[01;34mrun\x1b[0m \x1b[01;34msys\x1b[0m \x1b[01;34mvar\x1b[0m\r\n\x1b[01;34mcdrom\x1b[0m \x1b[01;34mhome\x1b[0m \x1b[01;34mlib\x1b[0m \x1b[01;34mmedia\x1b[0m \x1b[01;34mproc\x1b[0m \x1b[01;34msbin\x1b[0m \x1b[30;42mtmp\x1b[0m \x1b[01;36mvmlinuz\x1b[0m'
If this is in fact hexadecimal, how to I convert this back to a readable string for display purposes? If it's not hexadecimal, does anyone know what it is?
EDIT:
Since this is ANSI Color Control Codes, what's the best method to remove them?
prepend "\" to the beginning of the command
$ \ls
or provide handling for the escape sequences (strip, display)

Resources