Категория: In English @en

A lost game

A move many debaters try to pull off is setting up a lost game. It works like this:

“Punishing those who download books is unfair. They just take what was lying in the open. That’s a basic human right.”
“Yes they can reshare. You can’t punish for that either. They haven’t signed a contract promising not to do so. They are free to do as they wish.”
“Eh, okay. But surely, as a writer, I’ll just pen a contract by which anyone who buys and then shares is to be held responsible for all the millions of dollars of damages?”
“No, we cannot do this because that’s immoral. That’s basically enslaving him.”
“But then how do we protect the writers?”
“I don’t know? You want copyright, you think of something.”

Or like this:

“The government has no right to ban Freedom Hosting! They didn’t host CP, they hosted everything, that was just their business model: no restrictions.”
“Providers cannot be ordered to ban sites. That’s censorship!”
“People must be allowed to remain anonymous on the internet.”
“So you want to fight CP? We cannot ban the site, cannot ban the hoster and cannot find out who the owner is. I guess you have to sit and wait until the owner reveals itself, FBI! Know that I rooted for you.”

Negotiations don’t work like this. Either you don’t support the idea at all, or you see a point in it and then by the rules of discussion you must protect its interests to the extent you see it as important. In other words, if you agree you agree. No one is ever convinced by “I’d love to clean the room mom, but there’s a reason I can’t”.

That’s not how you should do it. There are several sides to the story and it’s okay to take one as long as you’re honest.
“I want there be a certain amount of uncontrollable freedom in the internet because total control is unhealthy for any society”. Absolutely.

See how the reaction changed? That’s because that was the truth. That was the idea that moved you, not the layers of justifications built around to make it “consistent”. And what moved one person may move another. You wouldn’t want to be held responsible for simply providing a hosting? Neither would I. It just feels wrong that one can go to jail for typing on the keyboard? Does so to me. You don’t want to be made to buy books, you want to buy books you liked? I can relate to that.

WordPress not remembering name or email for anonymous commenters

Someone reported that WordPress at boku.ru hasn’t been remembering the name and email which you enter in comments. I vaguely remembered this working before. After some investigation, turns out it was W3 Total Cache plugin which uses comment_cookie_lifetime filter to drop standard WordPress cookie lifetime from half a year to 30 minutes. And since my site runs as GMT, this was eaten by the 4-hour time difference.

W3 Total Cache did that because for cookie-less visitors it serves fast static version of the page (which can not be tailored for each visitor and have their name pre-entered, the way names are handled now). As long as you have posted a comment, you receive a cookie and WordPress serves you slower, dynamic version of the page. So the longer the cookie lifetime is, the longer you’re going to be served dynamic pages (but the longer your settings are going to be preserved).

This setting can be changed at “Performance > Page Cache > Advanced > Comment cookie lifetime”.

If you’ve stumbled upon this post while solving a related problem, here’s some additional pointers:
1. WordPress stores commenter name/email/url in cookies:

An example of how querying for these values should look like is in /wp-includes/comment-template.php/comments_template()

2. Your comment form is generated either by this, or by customization hook in your theme’s comments.php.

3. To debug cookies, add print_r($_COOKIES); to your theme’s header.php, don’t forget to remove it later. Use Wireshark or your browser’s request sniffer to track what’s being sent.

Can you repeat that?

Reading personal experiences on trimming the sizes of Delphi executables, I often encounter stories like this one:

I’ve moved from Delphi 2007 to Delphi XE3 and my executable went from 3Mb to 18Mb! I did this thing and that thing and disabled RTTI and set these flags and got the executable down to 16Mb. Nice, but not enough.
Then I discovered UPX and it reduced the size to 3.5Mb! UPX is magic!!

This is obviously wrong, it should make anyone with half a pint of a sense cringe – but why is it wrong? They got their size down. That’s what they wanted.

And then I figured:
Well, you got it down to 3Mb. Can you repeat that?

If Delphi XE8 comes out and your executable is suddenly 17Mb again, what are you going to do to trim it back? If you had spent several hours more and actually understood what happened and how to unhappen that, then you’d still be on a fair footing with the circumstances. Your trump card of using UPX and being excited would still be with you. And now it isn’t.

Right-click to copy web path for the file

Everybody who uses Dropbox have probably seen that you can right-click the file and “Copy shared path”, under which it is accessible in the internet.

I thought it would be nice to have similar functionality for BTSync and wrote the following sсript.

Code on pastebin.

Usage: put the code into “Copy links.cmd”, drop the shorcut to it into “C:\Users\[your username]\AppData\Roaming\Microsoft\Windows\SendTo” or wherever Sent To folder is in your versions of Windows.

Now suppose you have a folder C:\Download\images which is BTSync-ed to your server as http://example.org/lib/img. Create a file C:\Download\images\path.txt and write the above web base path to it.

Now select some files, right-click them and press “Send To -> Copy Links”. Web links for all the selected images are copied into your clipboard:

C:\Download\images\test\file.png --> http://example.org/lib/img/test/file.png

The sсript can also be used if you have a web server running at home which presents some of the files on your PC to the outside world, or even if you share some files and want to copy those as “\\mypc\share\path”. Since the sсript looks for the first available path.txt in the parent directories, you can link different folders to different addresses, or even copy and modify the sсript so that the same folder is linked to several base paths (“Copy as web address”, “Copy as local \\share”).


Bias is when you’ve picked a desired outcome before examining the issue. By presenting an objectively wrong party as having an equally valid position, you are biased in their favor.

flutterfly28 at reddit

This is the difference between being neutral and being neutrally biased. It’s true that many choose a neutral position because “the truth is always somewhere in the middle”, which is a bias. It’s also true that there is still usually more than one side to the story.

Shingeki no Sasha

Giants are attacking my town
And here I am, eating my potato
Peope are being killed right now
But baked potatos are good when they’re warm.

For those monsters people are just food,
In the same way potato is food for me
Why wouldn’t titans stop eating people
And start eating potatoes?

My combat gear lies beside me
Ready to fly me wherever I want
Potato fields are vast and well guarded
You can’t navigate there without some technical advantage.

Scout corps are the best of the best
They are the humanity’s only hope
If not for them, titans would surely win
And take all of our potatos, as well as kill everyone of course.

— Sasha no Kartoshka OP translation (provisional).

Multiobject try..finally

Just a simple Delphi pattern. We all have encountered nested try..finally blocks like this:

CChar := TTextTableCursor.Create(TChar);
  CCharProp := TTextTableCursor.Create(TCharProp);
    Builder := TCharPropBuilder.Create(Result);
      //Do some work with all three objects
      //Since all three are needed, we can't destroy any before this point

But there’s a nicer way of doing the same while still being exception safe (and avoiding the overhead of three try..finally exception frames):

CChar := nil;
CCharProp := nil;
Builder := nil;
  CChar := TTextTableCursor.Create(TChar);
  CCharProp := TTextTableCursor.Create(TCharProp);
  Builder := TCharPropBuilder.Create(Result);
 //Do some work with all three objects

Installing Delphi VersionInsight Plus

Since Delphi XE, Delphi has SVN support integrated into file history display. SVN revisions are displayed in addition to local backups, all properly sorted by date. Very nice.

Mercurial and Git support wasn’t added into the default distribution, but there’s a newer version of VersionInsight plugin with fully functioning support for those, written by Delphi developers. Meet RAD Studio Version Insight Plus.

To use this you need to compile it. It’s simple, but mind these fine points:

  • There are several branches in the repo, you need the /plus one. Not the trunk.
  • Delphi less than XE will not compile those, no simple solution.
  • You need to compile five packages: svn, svnui, svnide (already grouped into DelphiSVN) + hgide and gitide.
  • Delphi already includes pre-compiled svn, svnui and svnide. You need to remove those from “Component> Install packages” list. (And restart)
  • The ones from SVN are marked ver_150, and the ones with Delphi ver_170, but the ones from SVN are newer (I think).
  • When compiling the packages, Delphi might try to trip you up and use existing packages it cached somewhere instead of the sources right in front of it.
    To be on a safe side, do dir c:\svn*.bpl /s, dir c:\svn*.dcp /s, dir c:\svn*.dcu /s, and remove everything related to VersionInsight plus. (Some matches are going to be in the cached Delphi install distributions, these are fine).
    Particularly, svn*.dcp in Program Files\Embarcadero\Delphi\DelphiVersion\lib\Win32\debug or \release are known to silently cause problems such as svnui.bpl complaining that TSvnBlameOptions is not defined even though it’s defined right there in SvnClient.pas.

Otherwise packages compile just fine, have no dependencies and produce almost no warnings.

After compiling the packages, install the last three (svnide, hgide and gitide). Restart the Delphi.

The SVN support will start working straight away (it should have been working before too). For Git and Mercurial you need to go to Tools> Options> Version Control, and set paths to git.exe and hg.exe executables in the respective sections.

Atlas Shrugged

Well, people say Rand’s book is about how to be an asshole. It certainly seems that some of her opponents just don’t need the training.

HOWTO: Add your own feed reader to Opera’s default list

By default, when you click on an RSS feed icon, Opera displays feed contents in some basic format and allows you to subscribe to it with either the built-in reader or some of the popular ones.

But with the recent end of life of Google Reader many will switch to other, less popular readers, or perhaps even install one on their own server.

To add a feed reader to Opera’s default reader list, edit feedreaders.ini in “Program Files\Opera\defaults” folder. The format is obvious. There doesn’t seem to be an option for a per-user feed reader list.

For instance, if you’re using Tiny Tiny RSS, the subscription URL is per faq:


The code to add to feedreaders.ini will be: