Jump to content

aehimself

Members
  • Content Count

    1090
  • Joined

  • Last visited

  • Days Won

    23

Posts posted by aehimself


  1. 3 hours ago, Edwin Yip said:

    maybe the Delphi community/market is very small and we really need quality libraries and components.

    That is true; more that true actually. I remember back in the 2000s browsing Torry's Delphi Pages for components and I was not really able to choose from the incredible amount. Oh, and I remember how many were free!

    3 hours ago, Edwin Yip said:

    And my past experience shown that when a Delphi library/component is advertised as fast, it's usually fast, at least it proves the author really has a passion, or really tried to make it fast.

    Don't get me wrong, I'm not going to judge anything I have no experience with. Been there, done that, burnt myself, never again. I just gave an unpleasant grin to the "marketing".


  2. 42 minutes ago, David Schwartz said:

    Whatever you might think of SDs, I guarantee they won't decompose the way old magnetic media does over time.

    Ah yes, We used to compost floppy disks 😐 I already imagine the next-gen "uSD libraries" in data centers. At least the replacement drives would be cheap to order from Wish.

     


  3. 5 minutes ago, Lars Fosdal said:

    I love SSDs and I have not had one fail yet over the last six years.  HDDs, on the other hand, has failed me numerous times.

    As for backups - Online, multiple services = redundancy.

    The amount of numbers HDDs failed on us more is because SSD is much-much younger than HDDs are; but I already experienced SSD issues too. I still have an SSD in my laptop and in my dev server (with OS drives of guests on it) and they are still error free. I love them too; we all love them. But their lifespan is shorter than a HDDs - especially if we don't let that HDD to stop 🙂

     

    Edit: online backups are nice and should be safe enough. I just happen to be paranoid enough not to trust any big company.

    • Like 2

  4. Ahaaaa, makes sense. This is how IRC worked.

    To have a "private" chat, you have 2 options:

    1, Look in the source of the OnReceive event of the server. Instead of sending the received message to everyone, if the message contains a special flag, send it to one recipient only. For example, if you start your message with "@IP" then it will look for all connected clients, and where the IP address matches - send the message only there

    2, A more secure way is if you initiate a DCC-like (again, IRC did it this way) channel. If the message starts with @IP DCC, the server will send your IP address to @IP. Then, on your client, you open up a server socket and wait for a connection from @IP.

     

    Long story short, wither your message will travel around the network twice (thus, more vulnerable) or you have to establish a client-server connection directly between the TWO CLIENTS:

     

    image.thumb.png.4731987ec97add148fb6a90d5feb47f7.png

    • Like 1

  5. I know, it was only my very personal opinion and yes, I can be wrong. I guess - unless a component is really badly written - I doubt that it can cause slowdowns (there can be specific high-end cases where the design can cause a bottleneck but that's an other story).

     

    Back to your question. Usually there's not much to set a TCP connection up. You need a server (listener) component and a client (which is connecting to the server) component. Set the port number to the same, set the server and the client to active and it should work.

    Sending data is a completely different topic. Are you using text-based or binary communication? For text, most components have a .SendText method which will accept a string parameter. For binary - I don't think we want to go there just yet.

    Now look for events of said components. There should be something like... onReceiveBuf, onReceiveText, onDataAvailable... something like this - you have to handle those. And within that event handler, you have to read the data out of the socket with... socket.Read socket.ReceiveText, socket.receivebuf or something.

    Unfortunately that's all I can say, as I never used this component.

     

    Did you look at the Demo folder? There seems to be a chat application - just the one what you are looking for.

    • Thanks 1

  6. Just now, FPiette said:

    Are you doing backups now? Are you using RAID? Most today's mainboards have a basic RAID controller and if yours don't have one, buy one: it is not expensive at least for a basic version. High end version have a battery backup as well so that in case of power loss, the current duplication will continue and cache will be written to disk.

    Here we speak about source code, but today, almost everyone save his photos on hard disk as well. And many lost everything because they don't have a backup. Personally, I don't reuse SD card: I keep them as backup.

    Yes and yes. Since I have a dev environment at home I just added 2 extra hard drives mirrored (with daily automatic health check and warning E-mails). I do my development on my PC then syncing it upstream on a Git repository stored on this mirror. I have a physical RAID controller with a battery backup (salvaged a HPE P400 with 2 failed battery packs. Turns out it is using 4 AAA rechargeable batteries inside, so the quick fix was a matter of a bit of soldering) and the server is on a high capacity UPS.

     

    All this hassle for home, you are free to call me paranoid and I'm not going to argue 🙂

     

    P.s.: I'm not considering any flash-based (including SSDs) devices suitable for backup. Their write cycles are low and sometimes you recognize something failed when you are reading information back. And that's too late if it's used for backup. Minimum a mirrored HDD (which is always on, so not USB-attached which "I keep safe in the wardrobe and only use when necessary". It's good for power consumption, but it's bad for lifespan) but the best is still a tape drive - IN MY OPINION. I have personal privacy and safety concerns when it comes to "cloud" data storage.

    • Like 2

  7. My solution to something like this was to create a frame which contains only one row. Add basic functionality, like a grip and the resize code, initialization method, validation method, etc. Create as many variants as descendants of said frame as needed to handle different input / visual needs.

    Then, create one form with an alClient scrollbox and an alBottom panel with an OK and a cancel button. Give an array of data as an input to this form so it knows how many and what kind of frames it has to create in the ScrollBox.

     

    When the user clicks OK, you can see if all data is valid (because the validator is in the parent frame) so you can deny exiting.

     

    It ended up like this:

     

    image.thumb.png.fd10a6a4b786d54eaf17b1d145cf2a64.png

     

    I still need the resizing logic, though, it was a recent request 🙂

    • Like 2
    • Thanks 1

  8. 2 hours ago, FPiette said:

    All disk will fail one day!

    I learned that the hard way. In our country Quantum IDE hard-drives tended to fail often and suddenly (during power up the continuous click-click-click noise; I guess the arm was unable to move the heads?) but they were cheap so everyone used that.

     

    I lost ALL of my source codes of ALL of my applications one day. Thankfully, back in those days I wrote applications for myself and to a small number of people so I simply could say well, we use the latest version and no further improvements...


  9. Having a completely separate import application for each "client" seems to be a huge waste of resources. One half of each application is the same (the output part) so I'd have went on a totally different design approach. Have ONE import application with multiple import formats, descended from the same class... so your application is using the TMyImport class, and TMyImport_ABC0001 is a descendant of this. The single application then instantiates the correct class based on the channel where the data is coming from. Would make your lives a lot, lot more easy. It might sound like a lot of work, but one-by-one, slowly the change can be done. Just make sure you prepare TMyImport and the output part well enough 🙂

     

    Also, why to map C:\development to V:...? What difference does it make on which drive letter I'm changing my source code on? Please don't tell me you have hardcoded paths... 🙂

     

    Based on the example you gave, my script should work jus fine. Set C:\ as the root folder so it will try to refresh C:\Development (V:) and C:\imports (I:) too.


  10.  

    15 minutes ago, David Schwartz said:

    The challenge we have is we've got all of our production folders mapped to a couple of local drives (I: and V:) and each of those folders acts as the git base (whatever it's called).

    Well, you can create a folder somewhere and just add junctions with mklink (e.g.: MKLINK /D GitRepo1 I:\SomeSecretApplicaition\Git) to all of the git repositories you have. That will fool the script and will work on all of them. Or, modify the script and call :CHECK manually on each, instead of the for loop:

    CALL :CHECK D:\Doom

    CALL :CHECK Q:\Quake

    CALL :CHECK B:\BloodBorne

     

    15 minutes ago, David Schwartz said:

    So 'git pull' and 'git push" and so on act on the entire virtual drive. It can get rather convoluted when someone updates a file elsewhere that has nothing to do with what you're working on and it creates a conflict elsewhere that stops you in your tracks and you have to go off and resolve that conflict to continue work on what you're REALLY trying to do (that's not related at all).

    I understand nothing of this, especially the whole virtual drive part. Maybe it's better this way. At work we have one huge repository, with all the sources in it. Client, server, web, framework. All has it's separate folder.

    At home I have a different repository for my frameworks, they are located in my _DelphiComponents folder; far away from the applications which are using them. But, with this script everything can be refreshed at once, so no problem.


  11. It's pretty undocumented, but kind of easy to understand. Feel free to modify it to your needs:

    @ECHO OFF
    SET GITDIR=C:\LocalWork\_DelphiComponents
    SET OLDDIR=%CD%
    FOR /F "tokens=1 delims=" %%a IN ('DIR /B /A:D %GITDIR%') DO CALL :CHECK "%%a"
    GOTO :END
    
    :CHECK
    CD /D %GITDIR%\%~1 > nul 2>&1
    IF ERRORLEVEL 1 GOTO :eof
    "C:\Program Files\Git\cmd\git.exe" fetch > nul 2>&1
    IF ERRORLEVEL 1 GOTO :eof
    ECHO/|SET /P=%~1...
    "C:\Program Files\Git\cmd\git.exe" status > "%TEMP%\gitstatus.tmp" 2>&1
    IF ERRORLEVEL 1 (ECHO  querying status failed! & GOTO :DELEOF)
    TYPE "%TEMP%\gitstatus.tmp" | FIND /I "is behind" > nul 2>&1
    IF ERRORLEVEL 1 (ECHO  up to date. & GOTO :DELEOF)
    TYPE "%TEMP%\gitstatus.tmp" | FIND /I "nothing to commit, working tree clean" > nul 2>&1
    IF ERRORLEVEL 1 (SET STASHED=1) ELSE (SET STASHED=0)
    IF %STASHED%==0 GOTO :PULL
    "C:\Program Files\Git\cmd\git.exe" stash > nul 2>&1
    IF ERRORLEVEL 1 (ECHO  could not stash changes! & GOTO :DELEOF)
    :PULL
    "C:\Program Files\Git\cmd\git.exe" pull --rebase > nul 2>&1
    IF ERRORLEVEL 1 (ECHO  could not download updates!) ELSE (ECHO  update successful.)
    IF %STASHED%==0 GOTO :DELEOF
    "C:\Program Files\Git\cmd\git.exe" stash pop > nul 2>&1
    IF ERRORLEVEL 1 ECHO  could not restore changes!
    :DELEOF
    IF EXIST "%TEMP%\gitstatus.tmp" DEL "%TEMP%\gitstatus.tmp"
    GOTO :eof
    
    :END
    CD /D %OLDDIR%
    PAUSE

    For me it now outputted...

     

    image.png.2fe8f2e3387af7d4d283ca4b9a5120c5.png

     

    All you have to do is to change the path to the folder, where your Git repositories are. The script will check all folders within the root and if it's a Git repository it will do it's work.

     

    If you need help, feel free to ask.

    • Like 4

  12. On 8/21/2020 at 10:05 AM, Kas Ob. said:

    ICMP, this is a debatable subject but you can read about it but here an example and it is nice https://blog.securityevaluators.com/icmp-the-good-the-bad-and-the-ugly-130413e56030

    Nice article, it's always good to learn something new!

     

    On 8/21/2020 at 10:05 AM, Kas Ob. said:

    Notice in that article it all the advantage from blocking ICMP is useless when the same attacks initiated using different protocol, so what is the point of blocking ICMP when the attacker can achieve the same with TCP,UDP... ?

    What I meant is that - according to what you said - "No attack happens before a ping". I translated that as - if there's no reply, most hackers won't even bother with other ports as they will consider the target unreachable.

     

    On 8/21/2020 at 10:05 AM, Kas Ob. said:

    "Kali Linux"
    this one is very useful and i recommend to be familiar with, there is many resources about what it does take an example this https://www.youtube.com/c/DavidBombal/search?query=kali , that channel is nice and the guy does explain things slow and in details ( also not in much details as he have paid course) but it is fun to know using Kali and fun with friends in the same time.

    Know about it but never got further than installing it. When I had some free time I really wanted to do a scan of my home network to see what can be improved from security perspective.

    On 8/21/2020 at 10:05 AM, Kas Ob. said:

    "nmap scan host"

    Even smaller/lighter tools like https://nmap.org/ has many usages, can scan a completely blocked host by its firewall and report the OS type and may be even the version of the system without one open port, (try it for your self), most likely will detect the system with no open ports at all.

    https://nmap.org/book/man-os-detection.html

    Now we are talking! This looks absolutely terrific and terrifying at the same time. Just like human presence on the Internet. People can always know more about you than you want them to, especially if they know where to look!

    On 8/21/2020 at 10:05 AM, Kas Ob. said:

    The real deal is the following two, but those are depends mostly on what has been already discovered from security holes on almost every security hole on public domain, but still it is nice to be familiar with, but this is not easy to setup and run, used them in the past for long time, currently i don't use them, i do things my way.
    https://www.metasploit.com/

    https://www.rapid7.com/products/nexpose/

    I am a bit afraid of these stuff. I mean, real hacks were performed with Metasploit, it just sounds too "dark web"-ish just to satisfy one's childish interest in the topic.

    Ethical hacking is still hacking and noone will know your purpose once you start collecting tools to fool around.

     

    I guess I'll have an other look on Kali Linux. That seems to be a more... ethical choice for someone like me 🙂

     

    Anyway thank you for the resources. It's not only a hint on how to make our environment safer but what protection we can or should implement in the software we write!

     

    P.s.: it just hit me.... isn't metasploit a part of Kali...?


  13. 5 minutes ago, Dalija Prasnikar said:

    Additionally ternary operator has more broader usage scope than nullables themselves and thus is more interesting, worthwhile feature.

    Indeed. From C#, the only things I'd like to have in Delphi are:

    - Changing code while debugging (I know, possible because of JIT in .NET, so not going to happen but still, it's really-really useful)

    - Faster and more precise error insight and code completion (although, I regularly have to use my script to delete .vs folders because it goes nuts...)

    - Linq

    - Ternary operators

     

    I can live without everything else.


  14. 1 hour ago, David Schwartz said:

    Or do I need to run bash.exe and then provide git.exe as an argument to that, along with its parameters?

    No. Git bash is just an alternate shell to cmd with Linux-like commands. Yo can run git from your old and rusty cmd directly (ShellExecute / CreateProcess from Delphi) and it will work just as good as from Git Bash.

    I have a .cmd file to check all of my local git repositories and if there is an update upstream it pull-rebases all local branches, taking care of automatic stashing if necessary - it only stops for merge conflicts.

     

    Just double-click it and everything is as fresh as they are on their official repository.

    • Thanks 1

  15. I'm using this helper method to unzip the first file from a Base64 encoded string:

     

    Function UnzipBase64(inEncodedString: String): TBytes;
    Var
     ms: TMemoryStream;
     tb: TBytes;
     zip: TZipFile;
     zipstream: TStream;
     header: TZipHeader;
    Begin
     ms := TMemoryStream.Create;
     Try
      tb := TNetEncoding.Base64.DecodeStringToBytes(inEncodedString);
      ms.Write(tb, Length(tb));
      ms.Position := 0;
      zip := TZipFile.Create;
      Try
       zip.Open(ms, zmRead);
       If zip.FileCount = 0 Then Raise Exception.Create('ZIP file is valid, but it does not contain any files!');
       zipstream := nil;
       zip.Read(0, zipstream, header);
       Try
        zip.Close;
        SetLength(Result, zipstream.Size);
        zipstream.Read(Result, zipstream.Size);
       Finally
        FreeAndNil(zipstream);
       End;
      Finally
       FreeAndNil(zip);
      End;
     Finally
      FreeAndNil(ms);
     End;
    End;

    Could be shortened as far as I see, but it shows what you want. Open a zip file from stream, and extract a file from it to an other stream.


  16. 12 minutes ago, mvanrijnen said:

    Look out with the TZipFile class, there is a bug which causes empty zips when it gets too large (or you insert very big files)

    Do you mean Zip64?

    "The original .ZIP format had a 4 GiB (232 bytes) limit on various things (uncompressed size of a file, compressed size of a file, and total size of the archive), as well as a limit of 65,535 (216) entries in a ZIP archive. In version 4.5 of the specification (which is not the same as v4.5 of any particular tool), PKWARE introduced the "ZIP64" format extensions to get around these limitations, increasing the limits to 16 EiB (264 bytes)."

    • Thanks 1
×