2023-11-09 20:40 xxm474 [permalink]
→ xxm v126.96.36.1997 (→gh) (→sf)
'x'='','y'='1'in query string and form data (was
This is a relatively small release, but the NTLM/Negotiate change is too important (for security!) to wait too long with. Also the project entry cache should provide a performance increase in almost all cases. (Strange that I haven't noticed this sooner that this was a weak point!) So, in case you have projects that use NTLM (and
ContextString(csAuthUser)) to reliably identify users, It's very, very, warmly advised to switch to
"negotiate":true (instead of
"ntlm":true), and all should work exactly the same (for longer, and more securely). I considered just using 'negotiate' behind the scenes when
"ntlm":true is set, but I deem this distinct enough to make a separate setting and I guess security is a thing we should all be actively vigilant for. So they're both there for now, and a future release could drop NTLM. (Or it could be entirely missing from 2.0...)
Plans for the next release are mainly clean-up, for example deprecating xxmLocal (R.I.P. I.E.), and xxmRun (yes, I once thought people would use xxm from a CD-ROM, register it on auto-run and have the local Internet Explorer serve dynamic web-pages from an xxm project that uses the content from the disc... What was I thinking!). xxmGecko was already deprecated (yes, I once thought people would 'enjoy' — for lack of a better word — URL's in the address bar that start with
xxm://... What was I thinking!). With those out of the way I can do some more work on the underlying project entry registry, and have the project on in a good position to leave it for a while and maybe get started on 2.0... We'll see.
Update: there was a "v188.8.131.524" first, but had a bug in TXxmProjectCacheJson.FindProject, which would mingle projects between eachother when hot-reloading xxm.json... Be sure to update if you are running this version.
2023-10-15 20:23 noob [permalink]
There are no bad questions, there are only bad answers... I hope this wasn't too long an answer, but I guess I have everything I could think of:
2023-06-05 22:28 xxm466 [permalink]
It's been quite a while since I've done a release, and I regret that I wasn't able to offer more novelties with this release, but the fixes and improvements do make a solid release. By switching to Delphi Community Edition, I can now provide 32- and 64-bits editions. I have also included 32-bits binaries compiled with Delphi 7, for any case where you need to host (existing?) older
*.xxl files and need the exceptions handled. Newer Delphi versions have a binary incompatibility in the exception handling, which either results in exceptions not getting handled correctly, or a new access violation thrown instead by Delphi's internal exception handling. (If you prefer running mixed-delphi-version xxm-handlers and -project-binaries, consider exposing
IXxmProjectEvents1 by the project object, and use
HandleException to output a suitable message.
Also be advised, if you're updating from v1.2.4 or before, Web.xxmp's will still get converted from XML to JSON. (See the v1.2.5 release notes.)
→ xxm v184.108.40.2060 (→gh) (→sf)
WinHttpWS.pas: connect to a websocket using winhttp.dll
2023-03-30 23:02 WinHttpWS [permalink]
I needed to fetch something from a WebSocket real quick, but the project didn't have anything like networking components included yet. So I decided a quick-and-easy-way to get to what I needed is using winhttp.dll... I share this hoping it may come in handy for anyone else...
→ Github Gist: WinHttpWS.pas
2023-03-03 22:51 dirdiff646 [permalink]
→ DirDiff v220.127.116.116
There was a bug when diff-ing XML files. Incorrect characters were shown when (re-)indenting nested XML elements. I also upgraded the project to Delphi Community Edition version 10.4
Eszett: enter ß by typing Ctrl+Alt+S (AltGr+S)
2023-02-23 22:24 eszett [permalink]
When typing German on non-German keyboards, it's not entirely clear how to enter the "ß" character. There's charmap.exe and Win+"." but those are all pretty indirect.
Install eszett.exe to map the combination of Ctrl, Alt and "S" (or 'AltGr' if your keyboards has it, and "S") to enter a "ß" character.
(Source code available here)
My take on Free vs FreeAndNil
2022-06-25 00:52 FreeAndNil [permalink]
→ Coding in Delphi and beyond: Delphi Debates: FreeAndNil
;TLDR: I agree.
I, for myself, have a pretty straight-forward rule to follow. In most cases 'lifetime management' of objects is pretty plain and normal: there's one single place in the code where an object comes into existence (the call to a constructor), and exactly one single place in the code where it is cleaned up. In that case there's no reason that I can think of to use anything else than the
Free method. Sometimes the constructor is called from another constructor, and you free from the partner destructor, in effect linking the lifetime of the object to this 'owner' object. Most other cases, you just need an instance of a class to do something with. It typically looks like this:
Neat! One very (very) important thing to note here is that under no circumstance you're supposed to do anything with this object reference after that (other than assigning with a new constructor call etc.) Thanks to Delphi internals, you'll probably get an access violation, but you might just as well end up calling some code that has been put in the memory where the instance was, and has unintended consequences.
If, for any reason whatsoever, you need/want to write code that may or may not be assigned to a live instance of an object, you could and should use
nil. In the places in the code where it's not sure if there's an instance, be sure to check for a
nil value. Consider this snippet:
if //only in some cases
if a<>nil then
//use a for something
if a<>nil then
Seasoned Pascal-coders will have objections to this snippet, rightfully so, but the point I want to make that there's some extra steps taken here to 'keep it safe'. There's just this one thing that's not so easy to spot:
a.Free; could in theory throw an exception. If there's an
except clause below that, and it wants to get some data from
a, it won't work.
a isn't nil, but the constructor may have already taken down the object instance so far down it will no longer behave as expected. There's a way around that though, and you can see for yourself rightaway if you have a look for yourself at
procedure FreeAndNil(var Obj);
(There's some casting to/from pointer and TObject here, but that's to make sure it works in even the strangest cases. It basically sets the reference to
nil before calling
Free.) If you've seen that first without the context I described above, you might think 'what is going on here' or 'what is the fuss about'. So I hope I was able to bring some enlightenment. The best case would be if you've learnt nothing new here, and also agree with this rule:
If you have an abnormal object instance lifetime management situation and/or need to entertain instance references that may be
FreeAndNil. In all other cases use plain
Free (and keep calls to constructors and destructors in perfect balance!)
Delphi 10: "Debug" has "Use debug .dcu's" on by default
2021-09-01 18:48 d10debugdcus [permalink]
Since the community edition, and since it includes the command line compiler, I've been persuaded to switch some hobby projects I was sticking to Delphi 7 for. I've enjoyed a few of the new features I've been missing on (Ctrl+Shift+F! F6!), but also have noticed a few strange quirks I'm not so content with. [WARNING: what follows is my own opinion, you have every right to disagree and it is not at all implied you're doing anything wrong by disagreeing] If you start a new project, you get a "Debug" and "Release" configuration in the project, but the "Debug" project has the "Use debug dcu's" option checked in the project options under Building > Delphi Compiler > Compiling > Debugging. I regret that because when you follow what code does using the debugger and pressing F7 repeatedly, and you're not using the debug .dcu's, you only get to see code from your project. Especially for beginners, I think it could be quite jarring to end up in the thick of VCL-code without a clear way how to get out of there. (Shift-F8? Sometimes but not always.) If you F7 on a TStringList's LoadFromFile, it shouldn't descend into that unless you really need to and know what you're searching for down there... But that's just my opinion. Another thing that struck me is that local variables don't get zeroed by the 64-bits compiler, but I'm not sure if there's a switch or setting that controls that?
Ask HN: What is the SQLite of nosql databases?
2021-06-13 10:33 hnsqlitejson [permalink]
→ Ask HN: What is the SQLite of nosql databases?
Though I'm very much in agreement with:
The SQLite of NoSQL is still SQLite: https://www.sqlite.org/json1.html
there are situations where you could just use a single JSON object to store everything?
If your JSON implementation of choice does it correctly, and I attempted to get this right in my implementation, looking up a key from the list of key-value-pair should use a method that wastes no time and gets you to the value you want as swiftly as possible, no matter how many keys you need on the first level.
Then again, if you decide to use SQLite, and really need almost nothing else, I've created this one...
Do n.GetFirstChild=nil instead of n.Count=0
2021-03-21 17:25 nodecount0 [permalink]
I wish I knew this one sooner! If you've worked with TTreeView before, and know about TTreeNode's HasChildren value, you need to check with OnExpanding, if you need to load the children or not. So I would typically have something like this:
if Node.HasChildren and (Node.Count=0) then //load children nodes
Only now after all these years I happen to come past this in the Vcl.ComCtrls.pas unit:
function TTreeNode.GetCount: Integer;
Result := 0;
Node := GetFirstChild;
while Node <> nil do
Node := Node.GetNextChild(Node);
So I've been throwing away performance all this time! Because my 'are the children loaded yet' check was taking more time if they were and there were a lot of them, expanding nodes was slower. And I never noticed!
So it's a good thing I know this, and now I can just write:
if Node.HasChildren and (Node.GetFirstChild=nil) then //load children
205B random strings and no 'Delphi'
2021-02-28 18:48 randomdelphi [permalink]
→ Delphi-PRAXiS: Can Delphi randomize string 'Delphi'?
Ah, that takes me back. A while ago at work I got someone baffled by this statement: It is said that a thousand monkeys banging away on keyboards could at some moment in infinite time produce the complete work of Shakespeare (and that the combined internet forums are a living counter-proof). Now if you search online you can find an XML download of the combined works of Shakespeare, so it's not hard to find the relative occurance of each letter of the alphabet. One can guess this will have rougly the same values per letter as the total of the English language. So, then, if you take 'random' by its definition, and the monkey's produce text at 1/26 probability for each letter in the alphabet, therefore they'll never reach a point in time where they (re)produce the works Shakespeare.
Now, I'm not a real philosopher, or a statistician, so my thesis could be complete fiction and based on nothing, but sometimes you really got to take a lesson from practice. In theory, in infinite time, it's ofcourse possible that something really really inherently possible could emerge out of a random system, but there are characteristigs to anything random, and there are exponential things at play that soon but experimantal set-ups like with the link above, that they probably would produce the expected outcome in a time-span that exceeds the number of years we've got left before the sun sheds its outer layers and devours the earth, complete with a set of silicon-based machines churning away at putting a series of random characters in sequence and comparing them of some neat stories of a long gone English playwright.
DIY Google Authenticator
2021-02-25 20:12 diytotp [permalink]
Recently, I've got a few things asking to enable two-factor-authentication, and I started using the Google Authenticator app.
I kind of like it. It's a simple enough app, there's a shared secret involved, but it gets pretty close to being airgapped and perfectly forward secure and all of those things. So I got thinking... What would it take to start using it for myself, in those little software things I create now and then...
Is there black magic or stick whittling involved? Nah, a little searching around, and it all appears to be cleanly described in RFC's 6287 and 4226... There has to be a warning here about not rolling your own crypto, but the world of hashing and encrypting really is interesting! I did SHA1 and HMAC before, and Unix' time apparently is UTC... So all you need* is the correct format of URL to put into a QR-code to load up a new key in the app. Then you can use this code to generate the 'current' pass-code for the secret:
*: and apparently base32-encoding, HashUtils was missing that...
Lobsters on Delphi: the good and the bad
2021-02-18 00:20 lobsters [permalink]
→ Lobsters: 26 Years... of Delphi
Aaw, look at that, the good and the bad on a single page.
Good to know: don't do except on e:Exception do ... raise e;
2020-12-28 13:29 dontraisee [permalink]
Good to know. At work, I inherited a smaller project. It started firing access violation errors reading from 00000000 (that tells you there's a nil pointer involved somewhere) at some address that didn't put me somewhere in the source code when I did Search > Find address in the IDE...
I was lucky I got the program running in a debugger when this happens, and the root cause was something completely different. (An SQL unique index constraint violation if you're really interested.) I got that fixed soon enough, but that didn't explain where the access violation comes from.
I followed the exception with the debugger, and before the exception was handled by anything that outputs like a logger or an error display, sure enough an access violation happend, but the debugger didn't show me anywhere else in the source code than it was already debugging, strange.
It took me a long hard look at the code before I spotted it, but with some luck you'll be able to spot what's wrong faster. The original author had the strange habit of writing exception handlers like this:
//important stuff here
on e:Exception do
//stuff to do in case of an exception here, (e.g. transaction rollback)
And they were all over the place. Nothing bad about that per sé, with raising the exception again, you can centralise the actual exception handling on the 'highest level' where all the calls are made. But while you're able to raise a specific exception if you create a new one*, apparently there's a difference between
raise e; and
raise; at least in this Delphi version I was on. Delphi handles the destruction of exception objects for you, and apparently that throws something off and causes the nil access violation somewhere deep inside...
*: Fun fact: Did you know that the Delphi runtime system creates an EOutOfMemory exception instance at the start of your programs, just to have it ready when it actually runs out of memory anytime later? Forgot where I read about that though...
QuickReports: R.I.P. Lut
2020-12-18 16:26 invoicetemplates [permalink]
Oh my, I didn't know. I guess we'll see this more and more with one-person open-source projects, that people stop with the project for all kinds of reasons.
But about reports, I've made this really elegant thing at work to script the design of a report with just a few basic commands (line, text, image, matrix, block, repeat...) that allows you to write what the report should look like, and make lots of small alterations later. If you really need your reports just right, I've always found a graphical designer to introduce minor artefacts that you sometimes need to work around...
I know there are tons of similar things out there, like TeX and PostScript, and even HTML or MetaFiles, but it was grown out of neccessity and suffered "dogfooding" from the very start, which shows in its design and execution. And thanks to SynPDF, (or "Print to PDF" for that matter) you can just exports PDF's with it as well. So I really should take some time and re-do it on my own time and open source it... If I can make it even better and cleaner, I might introduce the open-source version as a replacement at work! (... Oh-oh!) (... or was it this one?)
Why no C++ webdev...
2020-06-05 17:23 cppwebdev [permalink]
→ Quora: Why is C++ not used in web development?
For what it's worth, in creating xxm it feels like I'm trying to create this exact thing except for with the Object Pascal language. Yes, you can do HTTP all by yourself, you can do an ISAPI extension DLL or a Apache httpd module, but you'll still get a strange hybrid between a server service and a web application that has nothing like a platform you can depend on to do the heavy lifting. And, if I'm permitted to speak frankly, in C++ this would be ugly! And probably would need a lot of code to make even the basic things happen. Too bad (Object) Pascal has been called verbose, if you know what you're doing you can write the logic you need in concise readable syntax.
Still what I'm finding in trying to get people to take a look at xxm, they either are unable to disregard the visual RAD form-designer style programming like I do, and don't get that xxm in it's current for is much more like early-days PHP but with the Delphi compiler instead of the script interpreter server-side; or they are fixed in thinking 'the web + Delphi' is all about a data-layer, doomed to only serve plain CRUD requests to and from a front-end layer, and never talk to the user's browser directly. Please! A big strong no on both accounts. Let me explain.
I've always seen — pretty much since FrontPage and DreamWeaver — that if you have a visual designer to manage what to go on a HTML page, you get really ugly code. It'll look the way you want, but a lot of decisions have been made for you. Some with negative consequences for you down the road. And the underlying code is strange and ugly, unneccessarily complex for your website-visitors' browser to work with. I guess modern front-end web-devs must have known this also as I've seen a regression towards working on big chunks of raw coding the last decade. Yes, font-ends are hacking away in CSS and HTML, and not with their bare hands, all kinds of CSS pro-processors and template engines do the heavy lifting behind. So if you know what you're doing, you can have this as well, in a Delphi project. I don't need a form designer, I make the page-builder first with dummy data, and run it in the browser. Don't forget, hitting F5 in the browser to an xxm website running over a development-handler, fires up the Delphi compiler there and then. Edit→Save→Refresh→Repeat
Then there's the other thing. If you start a conversation about webservers and Delphi, bam there's DataSnap. Strange. Is it because I'm strongly dys-convinced about ORM's? (Reminder to self: still have to write that grand essay about what's bad about ORM's.) Yeah sure, if you have things that use RTTI to serialize your data-objects in some way, you can easily use one of the available options to serve it over some web-server and bam you can call it REST and get away with it. But this is a completely different thing than having a full blown web-application serve from something you created! Complete with images and stylesheets. And yes you can have both🤯 from the same web-server-service🤯. I've had people walk away, unable to believe me. It still feels like it's a case of opening your mind to be able to see it.
Whaddayaknow, it checks out!
2020-05-27 10:30 primescheck [permalink]
→ J: Doc/Articles/Play104: The 10,000,000,000th Prime Number
http://yoy.be/home/primes/?a=2&x=10000000000&t=1&n=1 p(455052511)=10000000019 is actually the first prime past 10^10, but that does mean my primes thingy found the 455052511 primes lower than that.
Microsoft Teams was down?
2020-03-16 20:29 nottx [permalink]
→ Microsoft Teams goes down just as Europe logs on to work remotely — Verge
Tx wasn't down, especially the instance you host yourself.
About x in ['0'..'9'] and CharInSet
2019-11-05 22:42 anticharinset [permalink]
I'm still in the (slow) process of letting go of Delphi 7 and embracing the modern version(s) of Delphi, which to be honest was only possible since there's a community edition (that includes the stand-alone compiler(s)). I was in doubt if I would move over to the
WideChar based default
string, but since Windows internally switched long ago — and you get emoji-support for free — I thought I should switch also and haven't even tried to override the new default and switch
string to be
AnsiString just to keep things the old way. It works remarkably well. Any code that assumes the length of the string is also the number of bytes to move around needs to change, but that's a good opportunity to change them over to operations that use encoding support. With
char that also changes mapping (to
WideChar respectively) any coding use those just keeps working. Except in code like
x in ['0'..'9'] which I apparently use a lot. It works except when compiling it throws this warning:
Warning: W1050 WideChar reduced to byte char in set expressions. Consider using 'CharInSet' function in 'SysUtils' unit.
At first I was baffled. Why is it reduced to a byte char? I know set expressions trigger all kinds of compiler optimizations (that's why I like to use them so much), but has someone been too lazy to make them happen with 16-bit values as well? I guess we're talking assembler jump-lists here, so it probably matters if you can limit them to 256 positions, and 65536 positions would add too much of dead chunks of data into your compiled code... But still.
'0'-style literals should default to
WideChar, shouldn't they? So I regret there was no preference to support code re-use here, and CharInSet which appears to be just a wrapper around the
in syntax, strange.
I don't like warnings and hints. I typically avoid them at all cost, treating them as compile errors. It helps to keep your code clean, and avoids trouble down the line. (But if you're really into avoiding trouble down the line, you should do decent static code analysis...) I'm kind of strict on myself that way. So I need to know what's the best way to avoid this warning. In someone else's code I saw
x in [WideChar('A')..WideChar('Z')] but that doesn't appear to suppress this warning. So I settled on
AnsiChar(x) in ['0'..'9','A'..'F'] which probably calls a Unicode conversion routine, but I don't care enough. Old Delphi understands it, new Delphi no longer throws an error, and as far as I know the compiler optimizations still kick in and I haven't seen any performance loss over code like this. So I can sleep again.
Unless someone throws me a much better alternative and I won't sleep for a week because it feels like I should have known that all along...
Databases inside Delphi Ecosystem
2019-10-08 22:40 lgdbdelphi [permalink]
→ landgraf.dev: Databases inside Delphi Ecosystem: Webinar
Ugh, ORM? No thank you. I still need to write the full and extensive treatise about why exactly I prefer not to use ORM's, but every time I see something like "Databases in Delphi", and see the content rapidly veers toward heavy pre-moulded data-layers that bind you to things like ORM and REST API's, I regret so many people fall into this trap. Beginners think they're keeping things easy and scalable, but all hit the same wall later up when performance and complexity is letting them down hard, in part because of these basic choices made up front. I think it's very important to educate newcomers about the alternatives. There are downsides to ORM and heavy data-layers that you should know about.
Which I'm planning to address in a specific page "Why I dislike ORM's". One day. When I'm ready. For now I'll just say I'm glad I've stayed clear of them. I've looked beyond what's typically put forward as the only alternative, and went behind any platform, to talk to SQLite, PostgreSQL and MongoDB directly, unhindered. You get something working relatively quickly. It allows me to tap their full potential and have them scale right along with the front-end as it needs to grow to handle a larger volume of requests. I'm not saying it's perfect. This kind of architecture also has its downsides, but it has one big dependency less into the mix.
Feeder: support WordPress API "wp/v2/posts"
2019-09-14 23:40 wpv2posts [permalink]
Is it normal that a WordPress website serves it full "
https://api.w.org/" REST API from the home page (e.g. https://foreignpolicy.com/)?
I just happed to notice
<link rel="https://api.w.org/" href="..."> while I was looking for an RSS url. So I had to have a closer look. It looks like it's open for anyone to POST new posts to
Anyway, I've created support for it in feeder/eater...
PDF-web: tried forms but nought
2019-08-09 18:40 pdfweb [permalink]
A while ago I thought, since modern browsers show you PDF documents conveniently in the same window, could you make links work and have a dynamic webside that serves PDF pages?
But yes ofcourse you can. Then I also recalled it's possible for a PDF document to have form fields you can fill in. I tried, but the PDF viewers in modern browsers don't appear to support those. (Yet? Give me a ring if they ever do and I'll see what I can do.)
Update: Oh, what's this? Looks like they're working on it...
A PDF website
2019-07-14 00:54 pdfweb [permalink]
Also, in a PDF you can mark text or a rectangle as a hyper-link. So it should be possible to create a dynamic website that uses PDF instead of HTML, right? One way of looking at it is that PostScript in PDF is a way to layout things on your page just like HTML is.
Anyway, I had to see how much of work it would take to make a proof-of-concept. So here it is, it's not much on the dynamic side, but it's a site that opens to a PDF, and links to another page of the same site.
I'll be there: Delphi Day 2019 - Brussels 9 May
2019-04-23 11:39 delphiday2019 [permalink]
May 9: Delphi Day 2019
I'll be there.
Local variables don't cost nothing!
2019-03-08 22:45 nocostvar [permalink]
O my god. I can't believe I have to keep explaining this. To a years-long colleague with some more years on the counter than me, the other day. He repeated a function call with the same arguments a few times in a few adjacent lines of code, with a guarantee in place that this will result the same value every time.
I asked him why. It couldn't be to have less typing: the extra
var a:integer; would replace far much more code it took for the repeated function calls. It couldn't be performance: even if the function would just be getting a value from a memory location, the call and return, building a stack frame and tearing it down it again, would end up in a multiple of the instructions the processor needs to work through.
I don't know who launched the idea the compiler should be smart enough to pick things like this out — what I read about Rust and other modern languages, I know research is actively looking at things like that — but as we currently have it, our good old trusted compiler doesn't. What is does do, and typically really well if we work a little with it, is mapping local variables onto the available registers of the CPU. In the best case no memory whatsoever is allocated for local variables.
Even if in theory some local variables get a temporary address on the stack, modern CPU's have multiple levels of cache so that the values don't even reach your DRAM silicon before you're function call completes. We're supposed to keep all functions and methods as short as possible, but even if we don't, the compiler knows if a local variable is only used for a short section of the code. So in some cases it's even better to have an extra local variable instead of re-using a local variable somewhere up front and then later near the end of a larger block, and still not pay with any performance of memory consumption...
So when in doubt, take an extra local var. It's what they're there for. It helps the compiler do better analysis. It helps you, now and later. All I need to do now is name them a little better. I know I have the nasty habit of things like
var a,b,c,d,e,f,g:integer; but I think I'm improving... Slowly...