17

There seems to be various JavaScript+browser specific ways of decompressing this, but isn't there some way to transform jsonlz4 files to something unlz4 will read?

14

I was able to unpack the jsonlz4 by using lz4json:

apt-get install liblz4-dev
git clone https://github.com/andikleen/lz4json.git
cd lz4json
make
./lz4jsoncat ~/.mozilla/firefox/*/bookmarkbackups/*.jsonlz4
  • The andikleen solution is also good for .json.mozlz4 files e.g. as shown at github.com/andikleen/lz4json/issues/1#issuecomment-336729026 (note to self: remember, remember, gmake on FreeBSD …). – Graham Perrin Oct 15 '17 at 18:02
  • 3
    Also: bugzilla.mozilla.org/show_bug.cgi?id=1209390#c4 (2016-05-13) under Mozilla bug 1209390 - Use standard lz4 file format instead of the non-standard jsonlz4/mozlz4 draws attention to avih/dejsonlz4: Decompress Mozilla Firefox bookmarks backup files – Graham Perrin Oct 19 '17 at 1:40
  • 1
    FWIW, andikleen's tool failed to compile, with the error "undefined reference to LZ4_decompress_safe_partial" (I did install liblz4-dev prior to building it). avih's tool, OTOH, worked perfectly for me. – waldyrious Nov 6 '17 at 17:48
  • Isn't it ironic that an open-web org is using a proprietary compression format for user's data, making it non-trivial to examine your own data?! – cnst May 8 '18 at 4:42
  • @Graham-Perrin : dejsonlz4 worked very well for me. It doesn't "transform jsonlz4 files to something unlz4 will read" as requested but directly decompresses them. It would be good to make it a real answer to make it more visible. – mivk Jun 18 '18 at 18:26
8

Save this script as e.g. mozlz4:

#!/usr/bin/env python
from sys import *
import os
try:
    import lz4.block as lz4
except ImportError:
    import lz4

stdin = os.fdopen(stdin.fileno(), 'rb')
stdout = os.fdopen(stdout.fileno(), 'wb')

if argv[1:] == ['-c']:
    stdout.write(b'mozLz40\0' + lz4.compress(stdin.read()))
elif argv[1:] == ['-d']:
    assert stdin.read(8) == b'mozLz40\0'
    stdout.write(lz4.decompress(stdin.read()))
else:
    stderr.write('Usage: %s -c|-d <infile >outfile\n' % argv[0])
    stderr.write('Compress or decompress Mozilla-flavor LZ4 files.\n')
    exit(1)

Usage:

mozlz4 -d <previous.jsonlz4 >previous.json
mozlz4 -c <previous.json >previous.jsonlz4
5

Actually almost all Firefox profile lz4 files are mozlz4 files. It means they have the same "file format header". Except one file. I talk about webext.sc.lz4 file. It has mozJSSCLz40v001\0 file header and maybe some sc packaging to pack group of files to on byte stream.

There is a Firefox addon to read or compress .mozlz4 text files mozlz4-edit

2

Sufficiently persistent Googling for this turns up a lot of solutions, but most of them seem to be either (a) broken by subsequent changes to underlying libraries, or (b) unnecessarily complex (at least to my personal taste), making them clunky to drop into existing code.

The following appears to work at least on Python 2.7 and 3.6 using a recent version of the Python LZ4 bindings:

def mozlz4_to_text(filepath):
    # Given the path to a "mozlz4", "jsonlz4", "baklz4" etc. file, 
    # return the uncompressed text.
    import lz4.block
    bytestream = open(filepath, "rb")
    bytestream.read(8)  # skip past the b"mozLz40\0" header
    valid_bytes = bytestream.read()
    text = lz4.block.decompress(valid_bytes)
    return text

Of course this does not attempt to validate inputs (or outputs), is not intended to be secure, etc., but if one just wants to be able to parse one's own FF data, it gets the basic job done.

Command line version here, which could be saved in the relevant directory and invoked from the command line as:

chmod +x mozlz4.py
./mozlz4.py <file you want to read> <file to save output to>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.