IdWhois result with Unicode characters - delphi

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.

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.

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.

Error loading file with full name containing spaces in directory with delphi

I am using XE8, win 8.1.
When trying load a file with spaces in directory, I am getting a exception of syntax name of the file or directory is invalid.
If I use imageen dialog to preview the file, no erros are found.
I did two tests with the procedure load_file1 and load_file2 and I have the same problem.
Is there a wrokaround to solve it?
function get_file:string;
begin
result:='"C:\Compartilhada\dicomserver versoes\dicomserverx\data\Genesis-1000\1.2.410.200013.1.215.1.200912141600580009_0001_000001_13061821270002.dcm"'
end;
procedure load_file1;
var fStm:Tstream;
p1:string;
begin
p1:=get_file;
fStm := tFileStream.Create( p1, fmOpenRead or fmShareDenyNone ); //->Error Here
try
TBlobField(FieldByName('dicom')).LoadFromStream(fStm);
Post;
finally
fSTm.Free;
end;
end;
procedure load_file2;
p1:string;
begin
p1:=get_file;
TBlobField(FieldByName('dicom')).LoadFromFile(p1); //-->Error Here
Post;
end;
Remove the double quote marks from your string. It should be:
'C:\Compartilhada\dicomserver versoes\dicomserverx\data\Genesis-1000\1.2.410.200013.1.215.1.200912141600580009_0001_000001_13061821270002.dcm'
You might use " for paths containing spaces in some situations, for instance a command interpreter. But at the API level, it is simply not needed. And indeed it is a mistake as you have discovered. The double quote character " is actually a reserved character in a file name. That is documented on MSDN:
Naming Files, Paths, and Namespaces: Naming Conventions
The following fundamental rules enable applications to create and process valid names for files and directories, regardless of the file system:
...
Use any character in the current code page for a name, including Unicode characters and characters in the extended character set (128–255), except for the following:
The following reserved characters:
< (less than)
> (greater than)
: (colon)
" (double quote)
/ (forward slash)
\ (backslash)
| (vertical bar or pipe)
? (question mark)
* (asterisk)
...
...
In comments below you indicate that the code in the question does not reflect your actual problem. Which makes me wonder how you expect us to help. Your real problem is not the error message produced by the specific code, but that your debugging skills are letting you down. Let me try to explain how to debug a problem like this.
First of all, you are passing a file name to LoadFromFile or TFileStream.Create. These calls fail with an error that indicates that the file name is not valid.
So, when faced with that knowledge, the first step is to check the value of the file name that you are passing. Use debugging techniques to do that. Either the IDE debugger, or logging.
Once you have identified what value you are actually passing to these functions you can try to work out what is invalid about it.
To repeat, your real problem is not with the specifics, but in your debugging skills. You should take this as an opportunity to learn more about debugging. Stack Overflow is not a substitute for debugging. Learn to debug better, and your life as a programmer will become very much easier.

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?

Sending unicode command with TIdCmdTCPClient

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.

Resources