Wednesday, March 18, 2026

KMyMoney password doesn't work; can't open database

Did you recently upgrade your operating system?

Do you have KMyMoney 5.0 or above?

Did you try to open your kmymoney sqlite database and your password will not work (and you have no recollection of changing it, but maybe you did?!??)

Good news, you're not crazy. You're in the open source wild west.

KMyMoney uses sqlcipher for its encrypted sqlite databases. At some point it upgraded from sqlcipher 3 to sqlcipher 4, and the new version cannot open the old databases! They don't even tell you this, and neither does KMyMoney.

Luckily the fix is not hard.

1) Install the sqlcipher tool on your computer (eg, sudo apt install sqlcipher)

2) Open your database: sqlcipher path/to/mydb.sqlite

3) Run these commands:

After that, you should get a single row containing '0', indicating success (another number indicates failure). 

PRAGMA key = 'your_passphrase_here';

PRAGMA cipher_migrate;

you can .quit and uninstall sqlcipher if you choose.

Done. You should now be able to open your database with the latest KMyMoney. phew

Reference:  It's all made very clear in the second paragraph of the subsection on "File (SQLite/SQLCipher only)" in chapter 22 of the online manual

Monday, February 16, 2026

joe's own editor with ghostty



 There appears to be some incompatibility between the classic joe text editor and newer terminals such as Warp and ghostty which causes multi-line text which is pasted to the editor to lose the new-lines. In other words, all the lines in the pasted text appear on the same line.

This appears to be related to what is called "bracketed paste". This is a feature that allows multiple lines to be pasted at once, without the editor performing additional formatting that would happen if they were user-entered. In fact, joe seems to be the first piece of software to support this new feature of xterms back in the day.

Nowadays, most shell software supports bracketed paste, and that includes nano, pico, vi, and bash itself, as well as joe. But for some reason when joe's -brpaste config option is set to enable the feature (as is usually the default nowadays), the newlines are lost under ghostty.

The best workaround seems to be to disable bracketed paste support from joe, via the command line option --brpaste (note the second dash), or via the same in /etc/joe/joerc. This will cause pastes to appear correctly, but may cause ghostty to give a warning that such a paste may be dangerous. This warning can be disbled with ghostty's clipboard-paste-protection = false configuration option. If you're using bash or zsh, they also support bracketed paste, and as such should not execute the pasted commands until after you hit enter.

It's unclear why this happens in joe + ghostty. Bracketed paste to joe works in gnome-terminal. And bracketed paste from ghostty works in other software. Something similar was happening in nano/pico under macOS, and that was fixed. It appears that when gnome-terminal's vte uses bracketed paste, it sanitizes control characters before sending (pastify.cc:57-118). It also appears that joe has special handling for linefeeds (character 10) in bracketed pastes (main.c:152-153). So there may be unusual interactions showing up.

Monday, February 28, 2022

boost::asio tcp socket read with timeout

 You want to do a simple socket read in C++, using boost::asio. You're already in a thread dedicated to handling this connection, so it can be synchronous. Great.

size_t receivedLength = boost::asio::read(*socket, boost::asio::buffer(receiveBuffer), sizeof(receiveBuffer));

But then you realize you'll need a timeout in case something goes wrong on the other end, or it's taking too long or outside forces want you to abort. Should be simple, just add a timeout parameter, right? Wrong. Doesn't exist.

OK, well, you probably know that posix socket interface has optional timeouts. Just set the socket option SO_RCVTIMEO  and you should be good, right? WRONG! At least in Linux (and possibly elsewhere), boost::asio tcp read operations will not return at the timeout. They keep trying to read (see the aside here). It's a moot point, since it won't work anyway, but it's also finicky since the call to setsockopt is platform dependent. For posterity, this does the job:

// Set socket send & receive timeouts, after reading rcv default timeout
#define  RW_TIMEOUT_SECS 5

char timeoutBuf[16];
uint32_t sockoptlen = 16;
::getsockopt(socket->native(), SOL_SOCKET, SO_RCVTIMEO, &timeoutBuf, &sockoptlen);
if (sockoptlen == sizeof(struct timeval)) {
    std::cout << "Default receive timeout (s): " << ((struct timeval *) timeoutBuf)->tv_sec << " (us): " << ((struct timeval *) timeoutBuf)->tv_usec << std::endl;
} else { // sockoptlen == 4
    std::cout << "Default receive timeout (ms): " << *((uint32_t *)timeoutBuf) << std::endl;
}

#ifdef WIN32
const uint32_t timeout = RW_TIMEOUT_SECS * 1000;
#else
const struct timeval timeout = {RW_TIMEOUT_SECS, 0};
#endif
::setsockopt(socket->native(), SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout));
::setsockopt(socket->native(), SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout));

(There are asio methods to do this, but they are platform dependent and in linux/mac you have to implement a big class to use them.)


One option for having a timeout option would be to make the socket non-blocking, so async reads return immediately. Then, you poll to enforce the timeout yourself. So, you could do:

#include <chrono>
#define RD_TIMEOUT_SECS 5

socket->non_blocking(true);
size_t receivedLength = 0;
std::array<char, 1024> receiveBuffer;
auto error = boost::asio::error::would_block; clock_t start = clock(); while ( error == boost::asio::error::would_block
        && clock() < start + CLOCKS_PER_SEC * RD_TIMEOUT_SECS ) {
    receivedLength = socket->receive_from(boost::asio::buffer(receiveBuffer), 
                                         sender_endpoint, 0, error);
}
if (receivedLength > 0) { std::cout.write(recv_buf.data(), receivedLen); }

This is pretty clear and compact, but it kind of defeats the whole idea of asio, and wastes CPU time. Plus now you have to do more work to retrieve the number of bytes you expect/need. And finally, you probably also need to make sure that the connect function has a timeout, and this won't help you here. There are three other, better options, all of which work, each with slightly different drawbacks. 


The first option is the traditional, preferred asio method. It uses a deadline/steady timer and works with at least boost 1.44+. An example is here. In essence, you need to use an asynchronous read, create a timer with a timeout callback that would cancel the read if called, run the io_service (io_context in later versions) in a loop, and then check if there was an error (in the case of a timeout).

const int RD_TIMEOUT_SECS = 5
char receiveBuffer[1024];
size_t receivedLength = 0; boost::system::error_code error = boost::asio::error::would_block; boost::asio::async_read(*socket, boost::asio::buffer(receiveBuffer, sizeof(receiveBuffer), [&](const boost::system::error_code& result_error, std::size_t result_n) { error = result_error; receivedLength = result_n; }); try { // Set a deadline for the read operation. deadline_->expires_from_now(boost::posix_time::seconds(RD_TIMEOUT_SECS)); // Start the deadline actor to abort if still not connected deadline_->async_wait(boost::bind(&MyClass::checkConnectTimeout, this, _1, socket)); // Block until the asynchronous operation has completed. do { ioService_->run_one(); } while (error == boost::asio::error::would_block); } catch(std::runtime_error &e) { error = boost::asio::error::fault; } if (error) { std::cout << "Timeout reading socket." << std::endl; }

You'll also need to define your callback function to cancel the app. Both callback and boost::asio::deadline_timer deadline_ are class members.

void MyClass::checkConnectTimeout(const boost::system::error_code& ec, boost::asio::ip::tcp::socket *socket) {
    if (ec == boost::asio::error::operation_aborted) {
        // Timer was aborted.
        return;
    }

    // Check whether the deadline has passed. We compare the deadline against
    // the current time since a new asynchronous operation may have moved the
    // deadline before this actor had a chance to run.
    if (deadline_->expires_at() <= boost::asio::deadline_timer::traits_type::now()) {
        // The deadline has passed. The socket is closed so that any outstanding
        // asynchronous operations are cancelled and return an error code
        socket->cancel();
    }
}

A more compact application of this same approach can be seen here (to my knowledge it was first elaborated by Christopher Kolhoff on the boost mailing lists).


A simpler approach is possible from boost 1.68+, since you can run the io_context for a fixed amount of time using run_for(). This is shown in an example here. Basically, you need to create a new function to run the io_context and cancel the async read operation if it's not yet done when the time is up.

  void run(boost::asio::chrono::steady_clock::duration timeout)
  {
    // Restart the io_context, as it may have been left in the "stopped" state
    // by a previous operation.
    io_context_.restart();

    // Block until the asynchronous operation has completed, or timed out. 
    io_context_.run_for(timeout);

    // If the asynchronous operation completed successfully then the io_context
    // would have been stopped due to running out of work. If it was not
    // stopped, then the io_context::run_for call must have timed out.
    if (!io_context_.stopped())
    {
      // Close the socket to cancel the outstanding asynchronous operation.
      socket_.close();

      // Run the io_context again until the close operation completes.
      io_context_.run();
    }
  }

Then, you simply call it after the async read above, and before checking for an error.

const int RD_TIMEOUT_SECS = 5;
size_t receivedLength = 0;
boost::system::error_code error;
boost::asio::async_read(*s, boost::asio::buffer(receiveBuffer, sizeof(receiveBuffer)),
                        [&](const boost::system::error_code& result_error,
                            std::size_t result_n)
                        {
                            error = result_error;
                            receivedLength = result_n;
                        });

run(boost::asio::chrono::seconds(RD_TIMEOUT_SECS));

if (error) {
    LOG(lg::warning) << "Timeout reading socket" << std::endl; 
}

Similar techniques can be used for writing or connecting to the socket.


Finally, it is possible to use C++11's futures, as documented here

const int RD_TIMEOUT_SECS = 5;
std::future<size_t> futureReceivedLength =
  boost::asio::async_read(*socket,       
        boost::asio::buffer(receiveBuffer, sizeof(receiveBuffer)), 
        boost::asio::use_future);

if (futureReceivedLength.wait_for(std::chrono::seconds(RD_TIMEOUT_SECS)) 
    != std::future_status::ready) {
    std::cout << "Timeout reading socket." << std::endl;
    socket->cancel(); // cancel the operation.
    return; // do something appropriate; don't continue.
}

// this won't block because we know the future is ready. 
size_t receivedLength = futureReceivedLength.get();
// We can check the size and process the buffer

This is clean and standard, and you don't need any auxiliary functions. But you need to have the io_context run()ing in its own thread, which is probably wasteful depending upon your archittecture.

Hope this helps clear things up and save you some of the time I wasted figuring this all out.

Sunday, December 3, 2017

Installing and using opkg on recent DD-WRT routers

Sometimes you need to extend your dd-wrt router's functionality. As of current Kong builds  (at least 29000 to 34000), this is easy to do using optware and the opkg tool to install packages originally created for Open-Wrt.

But finding instructions to do so is hard. The best that can usually be found are something like this guide, which is largely out of date, and makes it sound much harder than it is. Or this which is likely also out of date and if it were to work would install a bunch of stuff you may not want or need.

All that is necessary in most cases** is:
  1. Enable JFFS under Administration->Management of the web control panel. After rebooting a nonvolatile /jffs partition will be created from flash memory.
  2. Telnet or ssh into your router (log in as root, with your admin user's password)
  3. Now, from the command prompt: make a directory to be used as /opt (where newly installed packages will be stored): mkdir /jffs/opt; mount --bind /jffs/opt
  4. Run bootstrap and say yes to install opkg. This is the well concealed secret. Bootstrap is included on Kong builds in order to install opkg for those who want it.
  5. Run opkg update to update the repository of available packages
  6. To be able to use opkg and installed packages after reboot, you need to add the line mount --bind /jffs/opt /opt to the startup script (under Administration->Management in the web control panel).
Now you have opkg installed and updated and can install packages. You can see the list of available packages by running opkg list and install them by running opkg install pkgname.

Happy opkging! Now you can do fancy stuff like install SSL certificates for your lighttpd web server.

---

Alternatively, rather than using the standard opkg, there's a new project called entware-ng which has more, and more updated applications to run on embedded devices.

To install this (which is in place of the normal opkg), skip step 4. Then follow the instructions here to install on DD-WRT (you could also install /opt on a USB device as explained there, but this is not necessary unless you want many apps or your router has little flash memory). I had luck finding some packages here that weren't available or working in the opkg repository.


* - Kong builds are for routers with ARM/Broadcom chipsets. I don't know about other chipsets or builds, but I wouldn't be surprised if brainslayer or others are building boostrap into their builds as well, so this approach may work for them too.
** - If your router does not have much or any available flash memory to create a jffs partition with, or you want to install many or very large packages, you will need to create a partition for use via USB, and mount it as /opt. Kong's own howto covers this (as well as some more tips on using opkg). The key is that you need a nonvolatile, writable subdirectory /opt, big enough to store what you want to install.

Sunday, April 23, 2017

Cadbury creme eggs ingredients


Cadbury's UK (as bought in Ireland):
Milk chocolate: Milk solids 14% minimum. Contains vegetable fats in addition to cocoa butter. Milk chocolate egg with a soft fondant centre (47%). Ingredients: Sugar, milk, glucose syrup, cocoa butter, invert sugar syrup, dried whey (from milk), cocoa mass, vegetable fats (palm, shea), emulsifier (E442), dried egg white, flavourings, colour (paprika extract).


Cadbury's US ingredients (as produced by Hershey's under license from Cadbury):
Milk Chocolate: (sugar, milk, chocolate, cocoa butter, milk fat, nonfat milk, soy lecethin, natural and artificial flavors), sugar, corn syrup, high fructose corn syrup, contains 2% or less of: artificial color (Yellow #6), artificial flavor, calcium chloride, egg whites.

These ingredients are from Easter 2017, so after Cadbury changed from using dairy milk chocolate in the UK.

Tasting them side by side, I was a bit surprised to find a significant difference. The UK eggs were richer and creamier, with a better flavor. The US eggs just tasted too sugary by comparison, and the fondant was more translucent, like sugar syrup.

Friday, March 10, 2017

Preventing Windows OS from sleeping while your python code runs

Do you have a python script that you want to run through to completion, but might take several hours without user interaction?

Might you run on a laptop or other Windows computer that has power management enabled, so that it might go to sleep or hibernate when not being used?

If you do nothing, windows will likely sleep or hibernate before your script can complete.

The following simple piece of code can prevent this problem. When used, it will ask windows not to sleep while the script runs. (In some cases, such as when the battery is running out, Windows will ignore your request.)

class WindowsInhibitor:
    '''Prevent OS sleep/hibernate in windows; code from:
    https://github.com/h3llrais3r/Deluge-PreventSuspendPlus/blob/master/preventsuspendplus/core.py
    API documentation:
    https://msdn.microsoft.com/en-us/library/windows/desktop/aa373208(v=vs.85).aspx'''
    ES_CONTINUOUS = 0x80000000
    ES_SYSTEM_REQUIRED = 0x00000001

    def __init__(self):
        pass

    def inhibit(self):
        import ctypes
        print("Preventing Windows from going to sleep")
        ctypes.windll.kernel32.SetThreadExecutionState(
            WindowsInhibitor.ES_CONTINUOUS | \
            WindowsInhibitor.ES_SYSTEM_REQUIRED)

    def uninhibit(self):
        import ctypes
        print("Allowing Windows to go to sleep")
        ctypes.windll.kernel32.SetThreadExecutionState(
            WindowsInhibitor.ES_CONTINUOUS)


To run it, simply:

import os

osSleep = None
# in Windows, prevent the OS from sleeping while we run
if os.name == 'nt':
    osSleep = WindowsInhibitor()
    osSleep.inhibit()

# do slow stuff

if osSleep:
    osSleep.uninhibit()

It is based on code from here, which also has code for preventing suspension on Linux under GNOME and KDE, should you need that.

Thursday, March 2, 2017

ufsd NTFS driver on mount: Fixing 'Unknown Error 1000'

I've previously mentioned using the ufsd driver for NTFS or HFS+, because it is significantly faster at writing than the default ntfs-3g driver provided with in Linux, and it supports writing for HFS+ drives even with journaling enabled. (It is available free for non-commercial use).

But what happens if you have a hard power down with an NTFS drive mounted? Or you encounter corruption for whatever reason?

UFSD may give this error upon mounting it for read-write:

mount: Unknown error 1000

This error is because the "dirty" flag is set on the drive and ufsd won't mount it read/write for fear of corrupting it. In many simple cases, you can correct errors in Linux with ntfsfix, from the ntfsprogs package, and also use ntfsfix to clear the dirty flag.

So if the volume in question is /dev/sdb1, I could do the following as root while the drive is unmounted. The first command repairs simple issues. The second clears the dirty flag:

root ~ # ntfsfix /dev/sdb1   
root ~ # ntfsfix -d /dev/sdb1

IMPORTANT NOTE: If you have extremely valuable data, especially that was being written when the failures occurred, you should be very cautious, because these commands may cause you to lose data.

A better approach may be to load Windows and run chkdsk /f  (to fix file system errors) or chkdsk /r (to detect and mark bad sectors) on the offending drive. Chkdsk is much more sophisticated at detecting and fixing errors than anything available in Linux, although it too may cause you to lose data (and some data loss may be inevitable if power goes off while writing). Here is one approach (using a bootable CD) to using chkdsk even if you don't have Windows installed or handy.

Final note, if this drive is not critical for your machine and you mount it from fstab, you can add the errors=remount-ro flag to the fstab mount line, in order to avoid hanging up your boot when things go wrong.

Saturday, January 28, 2017

Reinvigorating an old laptop with fresh Windows 7 and a new SSHD

I've got an older laptop running Windows 7 and it was getting bogged down by cruft after more than 4 years.

Windows update literally took over a week to check for updates last time I checked (pegging one of the processors that whole time). The lazy route would be to buy a new computer, and I looked into that. But I'm not happy with my options (long story), and otherwise, this laptop is great.

So I decided it was time for a hard drive upgrade for added speed and extra space, and re-install of the OS. As a benchmark, it took 3:30 to boot before I started (ouch!), with a 7200rpm hard drive.

After installing a fresh FireCuda 2TB hybrid SSHD drive at a very reasonable price (also in 1TB capacity), it was time to build the most lean Windows I could. (In my machine installing the drive was as easy as literally unscrewing one screw and swapping them out; google for your laptop's "service manual" if you're unsure of the procedure). If you're wondering why not install Windows 10, see below.

Start with the laptop's recovery media -- reinstall as it came, with Windows 7 pre-SP1. In my case, most drivers were not installed, and neither was Internet Explorer. I needed to manually copy over a Firefox installer in order to get going. And I attached an ethernet cable for internet, since ethernet worked out of the box (unlike wifi).

One of the main keys to keeping your install fast is to install as many updates as possible in as few steps as possible. The problem I had with windows update previously was because Windows Update performs a brute-force comparison of available updates against installed updates, and this gets massively slower as the number of installed updates increases. Here is what I did to keep things slim (links are for 64-bit Windows 7):
  1. Delete unnecessary and obsolete programs that came with your computer image (using uninstall tool, or removing the installers for things that you won't install).
  2. Install Windows 7 Service Pack 1 (KB976932) (if your image was from pre-SP1).
  3. Install the latest .NET framework (4.6.2 as of this writing). 
  4. Install IE11.
  5. Update Windows Update in order to install the rollups below (KB3020369)
  6.  * NOTE, I did not do this, but at this point it may be wise to install the "enterprise hotfix rollup" (KB2775511) and associated fixes mentioned at the bottom of this article, in order to avoid even more updates later *
  7. Install the rollup including almost all fixes to Windows from SP1 up until May 2016 (KB3125574) - this is "almost SP2"
  8. Google to install the latest "Security Monthly Quality Rollup" released either this month or last. For me I installed the January 2017 rollup (KB3212646) (you could install this even if you're doing it later; windows update can take it from here).
  9. Now install the latest drivers for your machine from the vendor's website. (If you have a Lenovo laptop like me, install only their System Update tool, which may also require you to install the .NET framework first, and then use it to update all of your drivers at once).
  10. Install Microsoft Security Essentials (or another antivirus software)
  11. Perform a few cycles of Windows Update and reboot; you'll still have maybe 40-100 security and optional updates.
  12. Delete installation files and do a Disk Cleanup (as administrator) to remove backups.
  13. Clone the machine from here to be able to recover more quickly next time, starting from this point. I used EASEUS TODO backupEASEUS disk copy is another potential option.
And you're set. Reinstall the software you use, and copy your data back on. 

For comparison's sake, I improved from booting in 3:30 to booting in 45 seconds, an almost 80% reduction (this is AFTER I re-installed all similar software). Nice!

P.S. - a few less obvious things you might have to do: 1) add a custom Inbound rule to the firewall with scope of your local networks, to allow other subnets to connect to your computer. 2) allow anonymous SMB access (you may also need to add user permissions to "Anonymous login" user), and note that many apps/appliances use SMB v1, so don't disable that


* So why not Windows 10? A few reasons -- one I'm completely happy with Windows 7. Don't fix what ain't broke. Next, I don't like that with windows 10 I'm at the mercy of upgrades from microsoft that I might not want but cannot decline, and which may break things. I also don't want many of the new features. And finally, I don't like the serious lack of privacy in windows 10 -- microsoft sends lots of data from your computer all the time. It's possible to lock it down somewhat, but it's tricky and always shifting (see above updates). Thanks but no thanks. Plus I missed the free upgrade window and definitely don't want to pay.

** If you buy the same great hard drive that I did from the link above, I'll get a small commission at no charge to you. Win-win!

Tuesday, January 10, 2017

Adjusted ADA scores from 1947-2015

Below you will find updated Americans for Democratic Action (ADA) scores covering the period 1947 to 2015 (the latest available). They are based upon ADA scores of selected congressional vote records independently tabulated by Groseclose, Levitt, and Snyder (1999) (for 1947-1998 originally and later extended by Groseclose to 2008) and Anderson and Habel (2009) (for 1947-2007), and have been updated and reconciled by myself (2008-2015). They are adjusted using the improved procedure from Dr. Groseclose, still based upon his original paper.

The final (adjusted) data are based upon the Anderson collection (mainly because when I started work that was what I had accessible). I correct over 150 mislabeled records that do not match valid ICPSR records as maintained by Keith Poole (as augmented with preliminary records for the 114th congress). Errors were often due to changes in seats, especially to people with similar names, or changes in party of the congressmen.

For the period 1990-2008, I additionally hand-corrected all discrepancies between the Anderson and Groseclose data. In some cases, records were missing from one source or the other. In others the scores were incorrectly transcribed or identifying data were incorrect. In a few cases the source data were ambiguous - in some years a score is provided even if the member served for less than half the eligible votes and occasionally the score does not match the recorded votes. Where possible, I trust the recorded votes over the scores, and omit any congressmen ineligible or deceased for more than half the votes. I also generally counted absences the same as negative votes, even if the congressman served a partial term (since this is ADA's general practice), although for 2007-2015 I omitted anyone who missed more than 6 votes (as I learned this was the practice of Groseclose et al.). There were around 380 such discrepancies and 150+ corrections. Given this work, the period since 1990 can be trusted to be of high accuracy. Earlier data still have discrepancies, and data prior to 1972 show a large number of discrepancies, which I highlight in the excel files provided below. These seem to largely be due to different policies for how to treat votes in years before a numerical score was assigned by ADA. I leave further correction / homogenization for future work.

I calculate the scores using two base years for the adjustment -- 1980 (as used in both the above papers), and 1999 (as used as the Political Quotient [PQ] in Dr. Groseclose's book Left Turn, which he chose because empirically that base year gives the average congressman in the 2000's an adjusted score near 50). If you would prefer a different base year, the code to produce it is below as well.


Downloads:

Adjusted scores with 1980 base year (.xlsx file)
Adjusted scores with 1999 base year (.xlsx file)
Raw data and code to reproduce (including raw output files and parameters) (.zip file)

Citations: The original papers above.

Wednesday, November 30, 2016

Simplified Fonts for ggplot2 in R

I struggled for a while to get fonts to work properly with ggplot2 charts in R under Windows. The solution turned out to be easier than it seemed. The "old" way was to use library("extrafonts") which would then scan your entire fonts directory each run (slowly). Then if you got that working and you wanted to export a chart to a PDF, say, you'd need to install Ghostscript and embed the fonts subsequent to generating it. Nowadays R can do it all internally, and with a bit of setup, not have to scan the fonts at all. That's thanks to the showtext and cairo libraries.

You just have to find the filename of the font you want from your fonts directory. (In windows, open control panel -> fonts, then view details and  you may need to add a "Font File name" column". If no name appears, it may be a grouping; open the grouping and do the same.) In my case I wanted to use the Perpetua font, which has the name PER_____.ttf.


install.packages("showtext") # once
install.packages("Cairo" # once
library("showtext")
library("Cairo") # for embedding fonts in PDF; may not need to be loaded here
library("ggplot2")

# add the desired font to the font database (you can add multiple)
font.add("perpetua", "PER_____.ttf")

# the following should only be necessary in windows, and often isn't documented
# for each font you add, do this, mapping the Windows name and type to a font family
# variable (Perpetua in this case) that you will refer to it as.
windowsFonts(Perpetua=windowsFont("TT Perpetua"))

# plot something
# and use perpetua font for text (by default - any text can be customized)
qplot(1:10) +
  + theme(text = element_text(family="Perpetua")) 

# save to file; using Cairo drivers to embed the fonts as needed
ggsave("mychart.eps", width=6.5, height=5.5, device=cairo_ps)
ggsave("mychart.pdf", width=6.5, height=5.5, device=cairo_pdf)

Note that you shouldn't need any special driver to save as an image file (jpg/png/...). I have encountered a few fonts that don't seem to embed correctly and I'm not sure why that is at the moment, but most fonts seem to work fine with this method; they are viewable on screen and in PDFs. This procedure should theoretically work cross-platform (except that the windowsFonts call will not be needed), which is another advantage to this method, although I have not yet tested this.

You can also use google fonts like so, so you don't even have to find one on your system:
font.add.google("Roboto", "roboto")

There is more about the showtext library here. Hope this helps you. Be sure to leave comments if you find any improvements to this method.

Thursday, September 22, 2016

Notes on using git and github

Everybody knows about github and what an amazing resource it is. This post is about using git with github.

Fork what you're interested in on github. In the following user is your username, repository is the repository you forked.
git config --global core.editor <your_favorite_editor>

You may want to modify the EOL settings to match your preferences and platform.

git clone http://github.com/user/repository.git
cd repository
git config user.name "user"
git config user.email "user@users.noreply.github.com"
git remote add upstream https://github.com/originaluser/repository.git

To integrate new changes from the upstream repo into yours:

git fetch upstream
git rebase -i upstream/master

If there are redundant commits, 'squash' them in the first "interactive" message. The -i is important; otherwise you'll get stuck with a bunch of redundant commits.

If there are any conflicts (changes to the same general area of code, even if just adjacent, or even if equivalent), you will be dropped to the command prompt commit by commit. Edit the conflicting file as it should be, removing any >>>>> or <<<<<. When satisfied, git add thefile and git rebase --continue. They will be applied in a new commit.

Similarly if you want to create a new branch for your own use:

git checkout -b branch

To switch branches at any time (without uncommitted changes), just omit the -b. If you want to instead create the branch at a previous commit, add that branch hash at the end.

Be sure to push any changes to the master branch to github before changing to other local branches. Then pull from github before rebasing.

Then you can rebase as above with the other branch. But if the other branch is pushed to github, it is dangerous to push if anyone else is using it. If you're sure they're not, you can git push --force while on that branch (if git config --global push.default simple). If there were any other users there, after pulling, they'd have to blow away their unpushed local commits with git reset --hard origin/branch.

Here is more on rebasing and merging: https://www.atlassian.com/git/tutorials/merging-vs-rebasing/workflow-walkthrough

Or you can move just one commit to the current branch by using:
git cherry-pick <hashcode>

If you need to clean things up: http://stackoverflow.com/questions/5916329/cleanup-git-master-branch-and-move-some-commit-to-new-branch

If you need to "undo" a change made on github, first pull to update your local repo. Then:
git reset --soft HEAD^, and 
git push origin +branchName (see caveats). 

About reverting, resetting etc, see: https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting

To update an existing remote branch from a local branch (which is currently checked out):
git push origin local_branch_name:remote_branch_name
or if the branch names match, do this and it will work in the future too:
git push --set-upstream origin local_branch_name

All in all my experience is that git is vastly inferior to mercurial (hg); git is far more finicky, harder to use and more prone to ugliness, and plus mercurial has nice GUIs from TortoiseHg. All in all, git feels like an advanced patch manager that has morphed into a version control system while mercurial feels like an advanced version control system. But alas, the linux kernel uses git and thus we have github and the rest is history. But I still use mercurial whenever I have a choice.

Saturday, June 11, 2016

Detecting CSS position: sticky support

If you're using modernizr for other things, by all means use that. If you just need a simple check to see if the current browser supports position: sticky, insert this javascript code:

var positionStickySupport = function() {
 var el = document.createElement('a'),
     mStyle = el.style;
 mStyle.cssText = "position:sticky;position:-webkit-sticky;position:-ms-sticky;";
 return mStyle.position.indexOf('sticky')!==-1;
}();

positionStickySupport will be true if it's supported. You should use the following CSS:


.myElement {
 position: -webkit-sticky;
 position: -ms-sticky;
 position: sticky;
 top: 0px;
}

Of course you can set top however you want. If you're wondering, the -ms-sticky is for future-proofing. As of this writing, Microsoft plans to support the feature in Edge, but it's not clear whether they'll use a prefix or not. Safari uses -webkit. Opera has it implemented in pre-release form without a prefix, and Firefox already supports it without one.

It would have been possible to use the CSS.supports() functionality, but Safari 6-8 support position: sticky but not CSS.supports().

Here is the one-liner version:

var positionStickySupport = function() {var el=document.createElement('a'),mStyle=el.style;mStyle.cssText="position:sticky;position:-webkit-sticky;position:-ms-sticky;";return mStyle.position.indexOf('sticky')!==-1;}();

Thursday, May 12, 2016

OpenVPN Server Setup Made Simple


For those not familiar with it, OpenVPN is probably the best and most secure VPN protocol out there at this time, with clients available for every mainstream platform. Unlike most other VPN protocols, it uses shared keys rather than passwords for security, which does make initial configuration take slightly longer.

But the real problem used to be that the process of setting up an OpenVPN server and generating appropriate keys was long, tedious, complicated, and error prone.

Those days are gone. There are now scripts that do all the hard work of setting it up and configuring users and keys for you. Answering a few simple questions, in a couple minutes you can have it up and running on your Linux server, and using all the current best practices to boot.

There are two use cases, and there are scripts for each, supporting at least Debian/Ubuntu/CentOS, which are both based upon the earlier work of Nyr:
  1. A multi-user, secure OpenVPN server, with quasi-anonymous usage.
  2. An OpenVPN server for personal use, supporting 3 simultaneous connections and potentially older clients.

In case one, use Angristan's script. To get it, run:
wget --no-check-certificate http://bit.ly/ovpn-install -O openvpn-install.sh
In case two, use jtbr's script, which is a lightly modified version of Angristan's.
wget --no-check-certificate http://bit.ly/openvpn-install -O openvpn-install.sh
You can click through to the link to see the extra security measures being taken by these scripts.
For either case, now simply run it as root after adding execute permissions:
chmod +x openvpn-install.sh
sudo ./openvpn-install.sh
For case two, if you want to change the number of simultaneous clients allowed, simply change the line max-clients 3 to the appropriate number before running, or remove it altogether for no limit.
The first run will set it up, and add the first client key (.ovpn file, which is placed in your home directory). Subsequent runs allow adding or removing clients or uninstalling. The generated client keys need to be (securely!) copied on to the clients' devices and imported into their OpenVPN clients. Once it's on their computer, this is usually drag and drop. For iPad/iPhone, I found the easiest option to be to use iTunes File Sharing to save to the OpenVPN Connect app. Then they can connect at will.
You're all set!

These scripts enable clients to access the internet and appear as if they are coming from the server's IP, a typical road-warrior setup; and depending upon the location of your server, to allow clients to access the server's local network. To allow VPN clients to connect to each other, or to allow access to the clients' network, then you'll need some additional routing configurationmore help here.

Especially if you're using a VPN for anonymity, you should also put some effort into ensuring your clients don't have any IP leaks (where your IP is discoverable by sites you access). A good guide to IP leaks and how to fix them is here; for a quick check, try here.

Wednesday, May 11, 2016

Touch-enabled swipeable scroll bars

Looking for an elegant, functional scrollbar solution for the web?

If you google around, you'll find TouchSwipe and various other Javascript-based solutions. These, while impressive, are trying too hard. They all have issues, either with handling links within the scrollable area, or with stutters in the animation, or with unnatural (on iOS anyway) non-bouncy ending of the scroll. I had several issues I could never overcome, not to mention their large code size and complexity.

You want something that works on touch devices and non-touch devices and is flexible and easy. I found the solution to be CSS-based, and this is it. It works on any modern browser and IE 9+.



The key is that you need an enclosing container (scrollWrapper) with overflow hidden, and an internal container (scrollableArea) that scrolls within it, and is allowed to scroll using the native facilities.

Normally, on a desktop, using the native scroll facilities would mean that you'd get an ugly scrollbar, so you need to hide that, and this can be done in CSS. But you need to replace that functionality for non-touch users. That means adding buttons on the ends that can move the scrollable area (and could also mean enabling the mouse wheel). The buttons call javascript functionw that simply update the scroll position and allows CSS transitions to occur. On the codepen below I even include a tiny javascript plugin that enables scrolling horizontally with a mousewheel (vertically would be automatic).

The result is something that's totally natural and totally flexible, and actually much simpler than the javascript solutions.

You can see a demo of the resulting scrollbar here

The HTML structure is trivial:

<div class="scrollWrapper">
  <a class="scrollBtn prev">&lt;</a>
  <div class="scrollableArea">
    <!-- stuff to scroll here -->  
  </div>
  <a class="scrollBtn next">&gt;</a>
</div>

The key part is this simple CSS code:
div.scrollWrapper {
 width: 96%;
 height: 91px;
 margin-left: 2%;
 position: relative;
 overflow: hidden;
 white-space: nowrap;
}
div.scrollableArea {
 position: relative;
 width: 100%;
 height: 125%; /* crop scrollbar (if applicable) outside scrollWrapper, while maintaining scrollability */
 white-space: nowrap;
 overflow-x: scroll;
 overflow-y: hidden;
 -webkit-overflow-scrolling:touch;
}

Note that the height is 91 in order to fit 81px-high divs with 5px margin on top and bottom. The scrollableArea height needs to be about 20px higher than the scrollWrapper to ensure that the desktop scrollbar will be cropped off.

Sample CSS for the scroll buttons:
.scrollBtn {
  display: inline-block;
  position: absolute;
  margin-top: 5px;
  margin-bottom: 5px;
  top: 0px;
  height: 81px;
  width: 30px;
  line-height: 81px;
  text-align: center;
  vertical-align: middle;
  background-color: #444;
  opacity: 0.5;
  text-decoration: none;
  z-index: 100;
  font-size: 30px;
  font-weight: 700;
  outline: none;
  cursor: pointer;
}
.scrollBtn:hover {
  opacity: 0.7;
  transition: 0.3s;
}
.scrollBtn.prev {
  left: 0px;
}
.scrollBtn.next {
  right: 0px;
}


Finally, here's javascript to handle the buttons and (optionally) enable horizontal scrolling (using jQuery):
$('a.scrollBtn.prev').click(function(e) {
 var scroller = $(".scrollableArea");
 scroller.animate({scrollLeft: scroller.scrollLeft() - (scroller.innerWidth() - 91)});
 e.preventDefault();
});

$('a.scrollBtn.next').click(function(e) {
 var scroller = $(".scrollableArea");
 scroller.animate({scrollLeft: scroller.scrollLeft() + (scroller.innerWidth() - 91)});
 e.preventDefault();
});

/** 
  * Enable scrolling an element horizontally using up/down mousewheel events
  * (when over the element). Amount is the number of pixels to move per
  * wheel turn (default 120) 
  **/
$.fn.hScroll = function (amount) {
 amount = amount || 120;
 $(this).bind("DOMMouseScroll mousewheel", function (event) {
  var origEvent = event.originalEvent, direction = origEvent.detail ? origEvent.detail * -amount : origEvent.wheelDelta, position = $(this).scrollLeft();
  position += direction > 0 ? -amount : amount;
  $(this).scrollLeft(position);
  event.preventDefault();
 })
};
$('.scrollableArea').hScroll(70);