yoy.be "Why-o-Why"

xxm v1.2.8.510

2024-01-08 17:48  xxm510  coding delphi freeware  [permalink]

→ xxm v1.2.8.510 (→gh) (→sf)

A quick follow-up release. I've had more reports of xxmHttp*.exe being wrongly identified as a Trojan horse, so I did more work on the code around the LoadLibrary call. (A very big thank you to VirusTotal. But that still doesn't fully guarantee it won't get flagged again now or in the future.)The NT-service versions apparently were broken, so I had to fix that. (And found a few more optimizations along the way!) I've been test-running a few days now and all works smoothly again. So be sure to update in case you've also ran into problems, otherwise nothing functional changed compared to revision 500.

twitter reddit linkedin facebook

tx as a service

2024-01-05 23:43  txsvc  coding delphi freeware  [permalink]

tx "stand alone version" is now available as an NT-service, since I added the files for xxmConv for it. (If you're interested, it's called from here.)
The original tx "stand alone version" was intended as a show-case to see if tx could work for you (and/or your team?), so it would only bind to 'local loop addresses' ('' for IPv4 and '::1' for IPv6, when available) for security.
But if you like it — and are not planning to do development on tx itself — this service version is what you need. You could install it on a server on the local network, so it's available to your entire team.
If you do want to tinker with tx itself, — it's an open source project after all — you're welcome to install xxm to host tx.xxl you build from source. (Hmm, should add a file with the steps in detail how to do that...)

twitter reddit linkedin facebook

xxm v1.2.8.500

2023-12-29 20:24  xxm500  delphi freeware  [permalink]

→ xxm v1.2.8.500 (→gh) (→sf)


Executable files xxmHttp*.exe may get misreported as malware of type Trojan horse ("Trojan:Win32/Bearfoos.A!ml" or "Trojan:Win32/Wacatac.B!ml" or others). Please configure exceptions where appropriate, or post false positive reports to your respective malware-detection-tool-vendor. Feel free to inform me of these cases. I have revised the code around the LoadLibraryW call as I suspect this is the most sensitive bit of code that the xxm handler may have in common with Trojon horse software, but I have no definitive means to be sure.

twitter reddit linkedin facebook

xxm v1.2.7.477

2023-11-09 20:40  xxm474  delphi freeware  [permalink]

→ xxm v1.2.7.477 (→gh) (→sf)

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 "v1.2.7.474" 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.

twitter reddit linkedin facebook

Noob questions

2023-10-15 20:23  noob  dagboek delphi  [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:

twitter reddit linkedin facebook

xxm v1.2.6.466

2023-06-05 22:28  xxm466  delphi freeware  [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 v1.2.6.460 (→gh) (→sf)

twitter reddit linkedin facebook

WinHttpWS.pas: connect to a websocket using winhttp.dll

2023-03-30 23:02  WinHttpWS  coding delphi internet freeware  [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

twitter reddit linkedin facebook

DirDiff v2.0.5.646

2023-03-03 22:51  dirdiff646  coding delphi freeware  [permalink]

DirDiff v2.0.5.646

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

twitter reddit linkedin facebook

Eszett: enter ß by typing Ctrl+Alt+S (AltGr+S)

2023-02-23 22:24  eszett  coding delphi freeware  [permalink]

eszett.exe ~2.3MB

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)

twitter reddit linkedin facebook

My take on Free vs FreeAndNil

2022-06-25 00:52  FreeAndNil  coding delphi  [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:

a:=nil;//counter warning
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 FreeAndNil itself:

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 nil, use FreeAndNil. In all other cases use plain Free (and keep calls to constructors and destructors in perfect balance!)

twitter reddit linkedin facebook

Delphi 10: "Debug" has "Use debug .dcu's" on by default

2021-09-01 18:48  d10debugdcus  coding delphi  [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?

twitter reddit linkedin facebook

Ask HN: What is the SQLite of nosql databases?

2021-06-13 10:33  hnsqlitejson  coding delphi  [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...


twitter reddit linkedin facebook

Do n.GetFirstChild=nil instead of n.Count=0

2021-03-21 17:25  nodecount0  coding delphi  [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;
Node: TTreeNode;
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

twitter reddit linkedin facebook

205B random strings and no 'Delphi'

2021-02-28 18:48  randomdelphi  coding computers delphi werk  [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.

twitter reddit linkedin facebook

DIY Google Authenticator

2021-02-25 20:12  diytotp  coding delphi internet freeware  [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...

twitter reddit linkedin facebook

Lobsters on Delphi: the good and the bad

2021-02-18 00:20  lobsters  coding delphi dotnet  [permalink]

→ Lobsters: 26 Years... of Delphi

Aaw, look at that, the good and the bad on a single page.

twitter reddit linkedin facebook

Good to know: don't do except on e:Exception do ... raise e;

2020-12-28 13:29  dontraisee  delphi werk  [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)
raise e;

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...

twitter reddit linkedin facebook

QuickReports: R.I.P. Lut

2020-12-18 16:26  invoicetemplates  coding delphi werk freeware  [permalink]

→ https://stackoverflow.com/questions/65348138/quickreport-on-delphi-sydney-10-4-1

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?)

twitter reddit linkedin facebook

Why no C++ webdev...

2020-06-05 17:23  cppwebdev  coding delphi internet  [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.

Anyway, sorry about the rant. I'm getting tired of trying to find the people that combine real web dev with Delphi for the server side. Yes there are a lot of new things that compile (Object) Pascal to JavaScript, but that's another story. That's nice for the front-end. But if you dig deeper, or want to reach the people that you can't offload your gargantuan client-side workhorse to, please think about xxm. Give it a try, see if you can make it work. If you want an example of what I'm talking about, take a look at feeder or tx.

twitter reddit linkedin facebook

Whaddayaknow, it checks out!

2020-05-27 10:30  primescheck  coding delphi  [permalink]

→ Primes...

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.

http://yoy.be/home/primes/?a=1&x=10000000000&t=1&n=1 p(10000000000)=252097800629

twitter reddit linkedin facebook

Microsoft Teams was down?

2020-03-16 20:29  nottx  actueel coding computers dagboek delphi werk freeware  [permalink]

→ Microsoft Teams goes down just as Europe logs on to work remotely — Verge

Tx wasn't down, especially the instance you host yourself.

twitter reddit linkedin facebook

About x in ['0'..'9'] and CharInSet

2019-11-05 22:42  anticharinset  coding dagboek delphi  [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 PChar and char that also changes mapping (to PWideChar and 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. x is WideChar, any '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...

twitter reddit linkedin facebook

Databases inside Delphi Ecosystem

2019-10-08 22:40  lgdbdelphi  coding delphi  [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.

twitter reddit linkedin facebook

Feeder: support WordPress API "wp/v2/posts"

2019-09-14 23:40  wpv2posts  coding delphi internet freeware  [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 /wp/v2/posts?!

Anyway, I've created support for it in feeder/eater...

twitter reddit linkedin facebook

PDF-web: tried forms but nought

2019-08-09 18:40  pdfweb  coding delphi internet  [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...

twitter reddit linkedin facebook


Archive... Search...