Jump to content

Remy Lebeau

Members
  • Content Count

    3006
  • Joined

  • Last visited

  • Days Won

    135

Everything posted by Remy Lebeau

  1. Remy Lebeau

    SysUtils, AnsiString

    The main problem with TEncoding.GetBytes() is that its 'public' overloads all require the output to be a TBytes array, which you would then have to copy into your record afterwards, eg: var patData : TPatData; SurName : String; Bytes: TBytes; begin FillChar(@patData, sizeof(patData), 0); SurName := ...; Bytes := TEncoding.UTF8.GetBytes(SurName); Move(PBytes(Bytes)^, patData.SurName[0], Math.Min(SizeOf(patData.SurName), Length(Bytes))); ... end; The one overload of GetBytes() that would actually let you output directly into your record without using TBytes is declared as 'strict protected', which means you can't use it without involving some hacks, eg: type TEncodingHelper = class(TEncoding) public function GetBytes(const S: string; Bytes: PBytes; ByteCount: Integer): Integer; end; function TEncodingHelper.GetBytes(const S: string; Bytes: PBytes; ByteCount: Integer): Integer; begin Result := GetBytes(PChar(S), Length(S), Bytes, ByteCount); end; var patData : TPatData; SurName : String; begin FillChar(@patData, sizeof(patData), 0); SurName := ...; TEncodingHelper(TEncoding.UTF8).GetBytes(S, PByte(@patData.SurName[0]), SizeOf(patData.SurName)); ... end; Or: type TEncodingHelper = class helper for TEncoding public function GetBytes(const S: string; Bytes: PByte; ByteCount: Integer): Integer; end; function TEncodingHelper.GetBytes(const S: string; Bytes: PByte; ByteCount: Integer): Integer; begin Result := Self.GetBytes(PChar(S), Length(S), Bytes, ByteCount); end; var patData : TPatData; SurName : String; begin FillChar(@patData, sizeof(patData), 0); SurName := ...; TEncoding.UTF8.GetBytes(S, PByte(@patData.SurName[0]), SizeOf(patData.SurName)); ... end; The alternative would be to use System.LocaleCharsFromUnicode() instead, eg: var patData : TPatData; SurName : String; begin FillChar(@patData, sizeof(patData), 0); SurName := ...; LocaleCharsFromUnicode(CP_UTF8, 0, PChar(SurName), Length(SurName), @patData.SurName[0], sizeof(patData.SurName), nil, nil); ... end;
  2. I don't understand what you mean. Please clarify. Is the event assigned a handler? If so, is the handler being called? If so, is the provided TIdSocketHandle object filled in with the correct port information? I don't see any port number being assigned in that code. So, unless the port number is assigned elsewhere after TTetheringNetworkServerCommUDP.Create() exits and before TTetheringNetworkServerCommUDP.DoStartServer() is called, then the UDP server will end up binding to a random port for each entry created in FUDPServer.Bindings. Really? uses ..., IdSocketHandle, IdUDPSerrver; ... var UDPServer: TIdUDPServer; ... UDPServer := TIdUDPServer.Create; UDPServer.ThreadedEvent := True; UDPServer.OnRead := DoUDPRead; UDPServer.OnException := DoUDPException; UDPServer.IPVersion := Id_IPv4; with UDPServer.Bindings.Add do begin IP := '192.168.10.30; Port := 2020; end; UDPServer.Active := True; ... procedure TMyForm.DoUDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); begin ... end; procedure TMyForm.DoUDPException(AThread: TIdUDPListenerThread; ABinding: TIdSocketHandle; const AMessage : String; const AExceptionClass : TClass); begin ... end;
  3. Interesting. I'm surprised that no error is being raised if TIdUDPServer is having trouble opening port 2020. Makes me wonder if it is even attempting to open the port in the first place. I don't know how Tethering uses Indy, can you show the actual code that sets up TIdUDPServer? Do you have the same problem if you use TIdUDPServer directly? Do you get an OnBeforeBind event fired for the Binding assigned to port 2020? Well, that makes sense, if there is no port being opened to accept the packets.
  4. No. But, on the other hand, what you provided in your last reply didn't really answer my questions at all. Did you VERIFY (ie, via netstat or lsof) that the IP/Port your server listens on is actually open successfully? Did you VERIFY (ie, with a packet sniffer) that network traffic is actually reaching your listening IP/Port? I'm not a Mac developer. I have no way to test this. But BSD-style socket APIs, like the one Indy uses internally, are largely similar/consistent across different platforms.
  5. Remy Lebeau

    Interfacing Unicode string to DLL PAnsiChar

    Oh, I didn't notice that directive. I don't know if it will work, though. I rarely ever use inlining.
  6. Remy Lebeau

    Interfacing Unicode string to DLL PAnsiChar

    Your 1st approach using StringToAnsiCPointer() will never work, since the AnsiString will go out of scope and be destroyed before the PAnsiChar pointer can be passed to the DLL. Your second approach using an AnsiString typecast at the call site will work fine, though you don't actually need the Length() check at all since an AnsiString consists of a nil pointer when empty, so you can just use that inner pointer as-is, by type-casting the AnsiString to a Pointer before casting to PAnsiChar, eg: function CompilerEncryptFile(const TextFileName: string; Key: TCNCEncryptKey; const EncryptedFileName: string): Longint; begin Result := _CompilerEncryptFile ( PAnsiChar(Pointer(AnsiString(TextFileName))), @Key, PAnsiChar(Pointer(AnsiString(EncryptedFileName))) ); end;
  7. Remy Lebeau

    Range check error.

    Yes, per the documentation:
  8. Remy Lebeau

    Convert C# function to delphi

    That was one of the formats I had tested, but it didn't get the same hash as the decoded base64 from the site's example.
  9. Remy Lebeau

    64 bit compiler problem

    Kind of hard to answer that without seeing your actual Delphi code.
  10. Did you verify that your UDP listening port is actually open, and that inbound data is actually reaching that port? If Select() returns false, it means the underlying OS reported that no data was available before the specified timeout had elapsed. What is your AcceptWait set to exactly?
  11. Remy Lebeau

    Range check error.

    Make sure that Count is not 0, otherwise Str[1] will report a range error if Range Checking is enabled. I would use PAnsiChar(Str)^ instead to avoid that check. Also, you are not checking ReadFile() for failure. Try this instead: function Tcomportserver.ReadString(var Str : AnsiString; Count : Integer) : Integer; var Overlapped : TOverlapped; BytesRead : DWORD; begin Result := 0; if Count <= 0 then Exit; SetLength(Str, Count); FillChar(Overlapped, SizeOf(Overlapped), 0); Overlapped.hEvent := CreateEvent(nil, True, True, nil); if Overlapped.hEvent = 0 then raise EWriteError.Create('Unable to create overlapped event object: ' + LastErr); try if not ReadFile(ComHandle, PAnsiChar(Str)^, Count, BytesRead, @Overlapped) then begin if GetLastError() <> ERROR_IO_PENDING then raise EWriteError.Create('Unable to read from port: ' + LastErr); end; if not GetOverlappedResult(ComHandle, Overlapped, BytesRead, True) then raise EWriteError.Create('Unable to read from port: ' + LastErr); SetLength(Str, BytesRead); Result := BytesRead; finally CloseHandle(Overlapped.hEvent); end; end;
  12. Remy Lebeau

    Convert C# function to delphi

    When I base64-decode that example digest, the SHA256 hash bytes are: 6b f8 28 22 8d 57 50 2a fc d2 b9 ca 14 25 a9 ef 24 69 c1 52 f9 d0 4f 51 6a e9 ee 10 78 75 d5 73 When I SHA256-encode the example JSON, I get varying results depending on how line breaks, whitespace, etc are handled: 61 4d f9 fe dd 28 e7 02 82 04 3b d1 62 fd 52 e8 7d 7c 55 16 87 a9 92 c7 65 08 ed b0 23 82 81 15 75 ca 3d a4 9c d7 c5 d1 c0 85 a4 b9 70 f5 9d 27 0c 7d 34 bd ac a1 92 ef b2 02 2f 6d a1 00 57 15 e0 71 09 2d 7c e3 49 be d3 5e 88 f8 ca 1b 94 c7 1a 49 f8 17 47 a4 a6 16 3e 0f 0f fd e7 f9 34 30 ce ea 16 24 4c 32 66 d3 30 4d 9b 23 a0 b4 0d cc 4a 9f 13 35 13 52 a3 c8 50 9e d1 52 ca a2 dd 8a d6 ef 0e 0a f6 5e af fd 1c 87 4a b9 09 2a 0c 6b 2e cf df 08 6c 5a 79 a7 ad 3a bd 1b c2 73 c2 c9 89 dd 42 34 69 e6 ec 47 a7 bb 9d ae d8 8a 9b 68 ce f1 06 7a bc 50 27 fd ae df f6 89 f7 56 ad f8 No matter what I do to the JSON, I can't get the same result as the decoded digest. So, I think maybe the website's example is wrong to begin with?
  13. Remy Lebeau

    base64 encode/decode  TStringDynArray

    Simply assign the (Unicode)String directly to the AnsiString, the RTL will handle the conversion for you. But like David said, you really shouldn't be using `AnsiString`, at least outside of direct interop with ANSI-based APIs. Stick with (Unicode)String natively for all of your processing, converting to/from bytes only when the string data needs to leave/enter your code (socket I/O, streaming, etc).
  14. Remy Lebeau

    Image attachment in a html email??

    Yes. TIdAttachment is an abstract base class in Indy 10, it has no such constructor. You are looking for TIdAttachmentFile instead. I suspect the code you are trying to compile is actually meant for Indy 9, not 10. In Indy 9, TIdAttachment was a concrete class that only supported files. TIdAttachment was redesigned in Indy 10 to be a base class with new descendants introduced (TIdAttachmentFile, TIdAttachmentMemory, etc). Also, the structure of your email is not setup correctly for HTML, with images. The article Lajos linked to explains in detail how it should be setup. And Indy has a TIdMessageBuilderHtml class to help with this task, see https://www.indyproject.org/2008/01/16/new-html-message-builder-class/
  15. Remy Lebeau

    TIdFTP read time out in FinalizeDataOperation

    Hard to say for sure without seeing the complete FTP sessions, but if I had to guess, the command connection in TIdFTP is likely being dropped part-way through the transfer, which would explain why the final response is not being received, and also why sending a QUIT request after the transfer timeout is causing a RST packet. Are you performing these transfers through a router/proxy/firewall, by chance? If so, they tend to drop idle connections after a few minutes, and thus are likely dropping the command connection during a large transfer since the command connection is sitting idle while the transfer is in progress. TIdFTP has a NATKeepAlive property to help avoid that issue, try enabling and configuring it as needed. You should filter the logs to isolate just the FTP command connections before saving them. You don't need 500Mb to show a handful of packets.
  16. Remy Lebeau

    TIdFTP read time out in FinalizeDataOperation

    I don't know what to tell you, then. TIdFTP is not receiving a final STOR response from the server. Since your FTP connection is not encrypted, have you tried using a packet sniffer like Wireshark to verify the response is actually being sent on the wire?
  17. That depends on what the thread actually does. Worker threads can have UIs and process user input, too. But, being that this code is running in a service, that is not likely to happen. So, if the thread has no UI, no keyboard input processing, then certainly TranslateMessage() can be omitted. But it doesn't really hurt to leave it in, either. It would essentially just be a no-op.
  18. Remy Lebeau

    TIdFTP read time out in FinalizeDataOperation

    In your log, I don't see a final response being received from the server for the STOR command, or the QUIT command. That would explain the timeout. Are you able to perform a similar transfer using another FTP client, like Filezilla, and get a final response after the transfer is finished?
  19. Remy Lebeau

    Playstore Android 64 bit APK, is it possible

    Have you read the documentation yet? Deploying Your Final Android Application Submitting Your Android App to Google Play
  20. Your message loop is not dispatching any system messages it receives. For example, asynchronous socket messages (since ICS uses non-blocking sockets). You need to call DispatchMessage() for any messages that you do not process on your own, eg: while GetMessage(lMsg,0,0,0) do begin if lMsg.message = _UM_Discover+fBaseMessage then begin if lMsg.lParam = _UP_DISCOVER_PARAM_ServerSettings then begin fdhsDiscover.FindServer; end; end else begin TranslateMessage(lMsg); DispatchMessage(lMsg); end; end;
  21. Remy Lebeau

    UDP sending and receiving

    You don't need to Listen() on a UDP socket. Only Bind() it, and then ReceiveFrom() on it. Listen() is only used for TCP. You can't Bind() to a broadcast IP, only to a local IP.
  22. Remy Lebeau

    UDP sending and receiving

    Connect()'ing a UDP socket assigns the specified peer IP/port as a static association, so that subsequent sends always go only to that peer, and only packets from that peer can be received. It also enabled better error reporting. If a send fails with an ICMP error, such as host/port unreachable, a subsequent send/read can fail with an appropriate error code. On a Connect'ed socket, you can use Send() and Receive(), you are not restricted to SendTo() and ReceiveFrom().
  23. Remy Lebeau

    Using VMWare: what files remain on host?

    Yes, each IDE would use its own default output folders within the VM. Source code is relatively small, so size was not an issue. Besides, I typically used fixed-sized VMs anyway. But no, storing the sources on the host did not affect the VM size. No. For me, being able to compile the same sources in multiple IDEs was important. If I changed something, I didn't want to have to copy the changes to multiple VMs to test it, just change it in one place only and then recompile as needed.
  24. Remy Lebeau

    Using VMWare: what files remain on host?

    In my case, I used to have one IDE installed on the host itself, and then a bunch of other IDEs installed in VMs, so I kept my source files on the host and used shared folders for the VMs to access the files. Worked fine.
  25. Remy Lebeau

    Bulk change of Manifest settings??

    I would probably just disable the default application manifest altogether in all of the projects, and point them all to an external manifest that they can share. Then changes are needed in only one place.
×