Skip to content


Why Tomtop’s products all have high ratings

For those who don’t know it, Tomtop is one of those sites that will ship you products straight from China, at pretty competitive prices. I recently bought a Xiaomi phone there, simply because Xiaomi still doesn’t bother to sell locally so buying abroad was my only option.

After browsing around the products a bit, I have yet to see a single product with an average rating below 4/5 stars. But I think I found the reason why.
That Xiaomi phone I bought, well it’s pretty bad. I mean, sure it works and it’s (very) cheap considering the hardware specs. However, I bought it primarily to experiment with LineageOS (RIP Cyanogenmod), and the bootloader is locked, and I spent almost 2 weeks trying to unlock it, with no success, and I eventually gave up. Xiaomi’s unlocking procedure, while straightforward on paper (request “permission” – I guess that’s the Chinese way of life -, download official tool, run said tool), is actually horrible and broken. If it works, good for you. If it doesn’t, you are screwed. They have no notion of what customer support means. The “support” is the forums, period. Forums where official staff barely ever intervene and lots of clueless people like to post their non-working solutions to your issues.

Anyhow, so of course I posted a negative review on Tomptop, precising that the phone was a PITA to unlock. And over a week later, said negative review is still not published. The review is in the system, I can view it in my member area (but not modify it), but it doesn’t appear publicly and isn’t counted in the rating or review count. The phone still has almost 5 full stars, with a bit less than 10 reviews. How many negative ones where kept in limbo? Only Tomtop knows…

So, don’t trust Tomtop’s ratings: the negative ones seem to be missing. And be also wary of the reviews: don’t get me wrong, I have no reason to believe they are fake, but since you only get the positive reviews you are only getting a very incomplete picture.

Posted in reviews.


How to transfer files on Android with ADB

For my current Windows installation, I chose an “N LTSB” version. N means without Media Feature Pack (no Windows Media Player, meaning it also lacks a bunch of codecs and some more surprising stuff), LTSB (for “Long-term servicing branch”) means that it’s free of shit like the Windows Store, Cortana, and most bundled apps (including Microsoft Edge). Also worth noting that unlike the default start menu of Windows 10, the start menu of 10 N LTSB is free of shitty tiles: there is only one, the “Contact Support” tile, which I consider an okay one, for once.

Among the surprising missing stuff in the “N” edition is, as I eventually was able to find out, the ability to browse a plugged smartphone using Windows Explorer. At first I thought this was a problem with the phone/Android drivers / ADB setup. But no, file transfers from an Android phone use the Media Transfer Protocol (MTP), which as its name suggests was included in the “Windows Media” framework. So on Windows N, no way to enjoy transferring your files the easy way.

The easy solution, of course, is to install the Media Feature Pack. But then there’s no point in getting an N version is it? (actually, I discussed with a Windows N user who told me they bought N because it was cheaper than the normal version in the store they bought it, in which case it does make sense to buy N and then download the Media Feature Pack)

The not as easy solution, which works nicely but might be not very convenient for a regular use, is to use ADB in the console. It’s actually fairly easy:
To get a shell on the phone (useful to browse and find the path to the files you want):
adb shell

Then you can browser like a normal Linux shell (cd path/to/folder, ls, etc)
To transfer a file from your phone to your computer:
adb pull /path/on/the.phone c:/path/on/the.computer

And to transfer a file from your computer to your phone:
adb push c:/path/on/the.computer /path/on/the.phone

For my path examples, I used Windows-style paths, but the commands are exactly the same on Linux or Mac OS.

On a side note, a notable path: although it probably depends on smartphones, photos and screenshots should be around /mnt/sdcard/DCIM and /mnt/sdcard/Pictures

Sources:

How to Push and Pull Files on Android using the ADB commands

Using adb To Copy Files To / From Your Android Device

Posted in multimedia, Windows 10.

Tagged with .


How to use pregenerated voice messages in game voicecoms

Lately, I’ve been playing a game called Friday the 13th. One of the originality of this game (which I don’t recommend at the moment due to the developpers’ very rude behavior towards the customers) is that it comes with a range-based voicechat: everyone, friend or foe, can hear you at a short distance, plus friends car hear you far away if both of you are equipped with a walkie-talkie.
This comes at a price, though: the devs thought it would be smart to only implement voicechat, meaning the game neither has text chat nor some kind of communication wheel with pre-recorded messages. In other words: no microphone = no communication. At all.

This sucks if: you do have no mic, or you don’t want to use a headset (mic can’t really be used without a headset because there doesn’t seem to be any kind of echo cancellation), or you don’t want to be noisy in the house because you play late, or if you’re a mute, etc.

People with no coms are also a weakness in the survivor (“counselor”) team, so eventually there was a rant topic on the Steam forums about people not using a mic, and in this thread a mute guy posted how he worked around the issue, by using software which basically created his own custom communication wheel. And here is how, with some tweaks so as to only use free (as in beer) or open source software.

Step 1: generate pre-recorded messages with text-to-speed software. Balabolka (freeware, Windows only) is nice for that, and very easy to use: type your message, choose between the 2 available voices (one male, one female), optionnally tweak it (I like to make it a bit faster, it saves time and since the pronounciation is good it’s still very understandable)

Step 2: install a “virtual audio cable” driver. That’s basically a driver that will create a device which can both act as a sound input and take sound input from another program. VB-Audio Virtual Cable (donationware, Windows only) will do nicely, and will be sufficient in its free version (if you donate, you get access to a version with more virtual audio cables, but you only need one for our purpose.

Step 3: get a soundboard software, like EXP Soundboard (open source and free, cross-platform – Java). This will allow you to map your sound files to hotkeys (I advise picking combined hotkeys, like ALT+X, so as to avoid accidentally playing sounds), and to send those sounds to both your speakers and your virtual audio cable. You can also configure the audio gain (separately for both outputs), meaning you can tweak the volume without having to redo your audio files, and you can choose different volumes from your local feedback (no need to make it too loud, this will allow you to hear game sounds better while “talking”) and your voice chat.
Of course, don’t forget to save your configuration 😉 It’s saved in a JSON file, which you should be able to manually edit if you want to re-order the sounds (which can’t been done from the software itself, apparently)

Step 4: don’t forget to configure your audio input in Steam, in Settings → Voice → Recording (audio input) device, otherwise the game won’t see it (that’s a little sad though, it means you can’t mix mic input and soundboard input – although I guess maybe the soundboard could be configured to also transmit mic input? I didn’t try that)

And voilà, you’re good to go. I didn’t go deep in each software’s details, but they are all pretty straightfoward so you shouldn’t have much difficulties setting them up.

Posted in multimedia, software.


And this is how I switched back from Vivaldi to Firefox

When Vivaldi came out a bit more than a year ago, I was rather enthusiastic about it, even though I remembered what the same people did to Opera and even though it was yet another Blink-based browser aka Google slave. I was always happy to add new browsers to my panel, in order to run multiple sessions simultaneously, and after all it was nice to have a fast browser for a change (Firefox/Cyberfox were still quite slow for me as I was on Win 7: they seem to perform a lot better on Win 10).

However, things eventually changed. First, Cyberfox was discontinued, and on this occasion I found out that it’s possible (and trivial) to run multiple independent sessions simultaneously with just Firefox. That was quite the revelation, and I promptly dropped Cyberfox and also Pale Moon, which was getting a bit outdated and was now failing to run Flash (having a contained Flash environment was basically the only reason I kept it around). After that, I was basically 60% Firefox, 40% Vivaldi.

Second, Vivaldi was regularly updated and improved. However, version 1.9 was a disaster: it completely broke the autocompletion in the address bar (it already used to be inferior to the autocompletion in Firefox, it became even worse, only providing one unique suggestion and only if you typed the exact beginning of the URL – worthless). I’ve also always been very unhappy with the SOCKS proxy support in Vivaldi, which is the same as Chrome = use the system-defined (same as Internet Explorer) proxy settings. I use one SOCKS proxy per separate session, so a browser not able to live its own life, distinct from the system settings, was a drag. Last but not least, I’ve always been annoyed by how Vivaldi doesn’t remember where to save/pick files on a per-site basis like Firefox seems to do pretty well.

At this point, I had only 2 reasons to keep using Vivaldi: Speed Dial, for which Firefox doesn’t seem to provide a suitable equivalent (no I don’t want to install an add-on just for that), and the fact that I couldn’t be bothered to migrate my session manually.

That was, until disaster stroke. I sent a tab to a new window, forgot all about it, and when I closed the browser I closed the primary window first. In case that shit never happened to you, what happens then is that when you restart your browser, the last closed window is restored (so, the one with just a tab, instead of my primary window that had 20-ish tabs). In Firefox, the History menu allows you to restore your 2 latest closed windows, meaning that in case you fuck up like that, you can easily recover (it happened to me a bunch of times). In Vivaldi, you’re fucked.
So, bye bye Vivaldi, I’ll just keep you around for testing when doing web development…

Posted in Chrome/Chromium/Vivaldi, Firefox.


JavaScript: passing arguments to setTimeout()

JavaScript prides itself on by asynchronous, which I find causes more complications than it solves, as in most cases I need code to execute step by step and not all at the same time. It makes, in my opinion, a lot more sense to have extra complications in the rare cases where I need asynchronous than to have extra complications in the very common cases where I need synchronous.

Among the trivial things that get unnecessarily complicated with asynchronous by default, is pausing. In many programming languages, when you want to pause, it’s just a matter of a trivial line, for instance:
– in PHP: sleep(X)
– in Python: time.sleep(X) (you need to import time for this to work, though)

In JavaScript, you’ll have to refactor your code, putting what you want to delay inside a separate function, and use setTimout(). That is, unless you want to saturate the CPU with an infinite loop for X seconds.

setTimeout() looks simple enough at first:

setTimeout(myDelayedFunction, 1000);

But there is a catch if you want to pass arguments. For instance, this won’t work (arg1 and arg2 will appear to myDelayedFunction as undefined):

setTimeout(function(){
    myDelayedFunction(arg1, arg2);
}, 1000);

To passe arguments to the function inside, you’ll have to use this:

setTimeout(function(A, B){
    myDelayedFunction(A, B);
}, 1000, arg1, arg1);

Or also this should work too (not tested)

setTimeout(myDelayedFunction, 1000, arg1, arg1);

Source and other variations there on Stackoverflow

Posted in JavaScript / TypeScript / Node.js, programming.


How to run multiple independent Firefox sessions simultaneously

For years (way over a decade, actually), I’ve used multiple browsers at the same time. What used to be a workaround to sites working better in some particular browser then became a very convenient way to keep several different sessions opened simultaneously (with 2 very separate “cookie world” and stuff). That’s useful for instance to be connected to 2 different mailboxes from the same provider, or to use different proxies simultaneously (one per browser).

But the browser world moves fast, and now it seems my favorite Firefox forks (Chrome support for SOCKS proxies is worthless so that’s not an option) are all vanishing: Pale Moon has been lagging behind for a long time, and now Cyberfox is being discontinued. Waterfox is still here, but they’re not really a fork, and they are so close to vanilla Firefox that they actually share its profiles and session (if you try to run Waterfox while Firefox is running, or the other way around, it will tell you Firefox is already running). So, it’s becoming hard to find distinct browsers.

In my despair, I tweeted to Waterfox about that problem of not being able to multi-session, and they pointed me to the -no-remote flag. I already used several Firefox profiles, but so far I was only able to run a single one at a time. What that flag does is that it basically allows to run several profiles at the same time (to use it, edit your Firefox shortcut and add it at the end of the command line). I guess I should have searched harder.
Problem solved already, then 🙂 But now, every time you run Firefox the profile manager will pop up. If you want to skip this, you can create separate links for each of your profiles, by adding also -P “profile_name” in the command line. Or even -profile “profile_path”, if you like moving stuff around 😉 All those options are detailed in the link I gave previously.
NB: I put the same case as in the documentation because I didn’t want to test everything, but I’m pretty sure all those options are case-insensitive.

Last but not least, a little advice to avoid mixing up your sessions: set them up each with a different theme ^^

Posted in Firefox.


Please stop confusing deep web, dark web and dark net

Those are 3 different things. Let’s review.

Surface web

That’s the portion of the World Wide Web that is freely, directly accessible, and searchable with standard web search engines. Obviously you know that one and use it every day.

Deep web

It might come as a surprise for some of you, but surely you do use it every day too.
It’s basically the opposite of the surface web. Also called invisible web or hidden web, the deep web is all the parts of the World Wide Web that are not indexed by standard search engines. That’s the definition provided by Wikipedia, but I believe a site tagged “noindex” is still surface web, as long as access is free and doesn’t require registration or some specific technology (cf darknets below).
For instance, most parts of Facebook (all content that isn’t posted as “public”) is part of the deep web. Your web mail, your online banking accounts, contents behind a paywall, etc are “deep web” too. Told you you use it every day 😉

Dark net

Before talking about the dark web, we need to talk about dark nets (with an s).
Wikipedia provides a pretty good definition there: “a darknet (or dark net) is an overlay network that can only be accessed with specific software, configurations, or authorization, often using non-standard communications protocols and ports.”
Nothing to add, really. For instance, Tor is a darknet, Freenet is a darknet, GNUnet is a darknet, I2P is a darknet, etc. So, again, there are several darknets. Let’s say, about a dozen “big” ones.

Dark web

Wikipedia is straight to the point again: “The dark web is the World Wide Web content that exists on darknets” (so you see why I had to define a darknet first).
So whatever is on Tor, Freenet, etc, is on the dark web (and also on a dark net).

It is typically said that the dark web forms a small part of the deep web. I prefer to consider them as 2 distinct entities, as the barriers are distinct enough: the deep web is behind a login wall, the dark web is behind a networking technology “wall”. Also, some parts of the dark web (like some marketplaces) are behind both a networking technology and a login wall.
But if you are comfortable enough with those notions to start arguing about this detail, you know enough already 😉 (and sadly, you also know more than the average IT journalist :/ )

Bonus: clearnet, opennet, etc

Clearnet is a term used by dark web users to describe the regular internet. Since most darknets are focused on anonymity, it’s a convenient way to talk about “that part of internet where you are tracked”. Contrarily to what used to be mentioned on Wikipedia’s “surface web” page, clearnet is NOT synonymous with “surface web”. Facebook is clearnet, but as we saw earlier a lot (most?) of it is deep web.

Opennet is a more uncommon term. I only know about it in the context of Freenet. In the Freenet network, you can use 3 ways to connect: you can either connect only to people you know (real life friends), or connect to strangers, or do both. When you connect only to people you know, Freenet calls that “darknet”. When you connect to strangers, Freenet calls that “opennet”. Even though technically both are “dark nets” in the usual definition, at Freenet’s level the difference makes sense.

Posted in Internet, privacy.


Uninstalling dependencies of Python pip packages

pip is the package management system included in Python 2.7.9+ and 3.4+. It’s quite convenient to install packages, even though I’m not a big fan of having shitloads of packages around, particularly since their number can quickly grow to unreasonable proportions with all their dependencies. And as a matter of fact, pip installs package dependencies, but… it doesn’t uninstall those dependencies when you uninstall the package they were installed for.
For f***ing f*** sake.

Anyhow, there is a way to uninstall dependencies when uninstalling a package. It’s another package (which I believe has no dependencies itself), called pip-autoremove. So, basically, if you want to cleanly uninstall package “examplepackage”, you’d go:

pip install pip-autoremove
pip-autoremove examplepackage -y

It’s worth noting that, normally, it should only remove unused dependencies. It actually even provides a feature to just list packages which are not a dependency of any other package (-L flag)

Since it’s so short, here is the help:

> pip-autoremove --help
Usage: pip-autoremove [OPTION]... [NAME]...

Options:
  --version     show program's version number and exit
  -h, --help    show this help message and exit
  -l, --list    list unused dependencies, but don't uninstall them.
  -L, --leaves  list leaves (packages which are not used by any others).
  -y, --yes     don't ask for confirmation of uninstall deletions.

Posted in programming.


How to block base64 images with uBlock (and other things)

Some websites are really imaginative to try and bypass ad-blockers. Although their methods are interesting to study sometimes, usually when sites bother placing anti-ad-blocking code they tend to use it to place particularly annoying things.

One site I visit sometimes uses quite a dirty method: they place all ad images _inline_, as base64 encoded data.
I don’t think any uBlock filter catches those, as it would require site-specific filters instead of the usual advertising network-specific ones. However, you can easily make a filter yourself. Go to uBlock options (if you don’t know where to find them, click the uBlock icon to pop up the uBlock GUI then click the tiny cog in the top-left corner – yes I had a hard time finding it too a long time ago :s), then to the My filters tab. And add a line like:

example.com##img[src^="data:"]

And that’s all (make sure you replace example.com with your target site, of course). Just hit “Apply changes”, and when you reload the site the base64 images should be gone.

While I’m at it, here is some more useful filter syntax:

example.com

=> blocks a whole domain name. Useful to block an advertising network that isn’t supported yet in the published filters. Or also to block a site without installing a specific add-on such as BlockSite

example.com##.some-class

=> blocks all elements of class “some-class”.

example.com###some-id

=> blocks all elements of ID “some-id” (well, normally IDs should be unique so that would be only 1 element).

example.com##script:contains(sendAdBlockEventGA)

=> blocks script that contain the keyword “sendAdBlockEventGA”. I’m not really sure of the extent of what is blocked (just the line around the detected word, I assume?), and also maybe this only works on Firefox. Well, long story short that’s not a filter I actively use at the moment, but still I suppose it can be useful for instance to block those big fat popups saying “HEY YOU PLEASE TURN OFF THAT ADBLOCKER”. Yup, I should definitely try to remember to give it a spin next time I see one of those 😉

Posted in privacy.


How to generate a strong random hexadecimal string in Node.js

…and using TypeScript syntax. Simply use the “crypto” standard library.

import * as crypto from 'crypto';
const randomString = crypto.randomBytes(32).toString('hex');

Note that it will produce cryptographically strong pseudo-random data, but the drawback of this is that it will freeze a bit in case of a lack of entropy. As mentioned in the documentation, such lack of entropy shouldn’t ever create a noticeable delay, except right after system boot.

Posted in JavaScript / TypeScript / Node.js.