GithubHelp home page GithubHelp logo

threeplanetssoftware / apple_cloud_notes_parser Goto Github PK

View Code? Open in Web Editor NEW
370.0 8.0 24.0 353 KB

Parser for Apple Notes data stored on the Cloud as seen on Apple handsets

License: MIT License

Ruby 96.58% Python 1.95% Dockerfile 0.25% Shell 0.83% Roff 0.40%

apple_cloud_notes_parser's Introduction

Apple Cloud Notes Parser

By: Jon Baumann, Ciofeca Forensics

About

This program is a parser for the current version of Apple Notes data syncable with iCloud as seen on Apple handsets in iOS 9 and later. This program was made as an update to the previous Perl script which did not well handle the protobufs used by Apple in Apple Notes. That script and this program are needed because data that was stored in plaintext in the versions of Apple's Notes prior to iOS 9 in its notes.sqlite database is now gzipped before storage in the iCloud Notes database NoteStore.sqlite and the amount of embedded objects inside of Notes is far higher. While the data is not necessarily encrypted, although some is using the password feature, it is not as searchable to the examiner, given its compressed nature. This program intends to make the plaintext stored in the note and its embedded attachments far more usable.

This program was implemented in Ruby. The classes underlying this represent all the necessary features to write other programs to interface with an Apple Notes backup, including exporting data to another format, or writing better search functions. In addition, this program and its classes attempts to abstract away the work needed to understand the type of backup and how it stores files. While examiners must understand those backups, this will provide its own internal interfaces for identifying where media files are kept. For example, if the backup is from iTunes, this program will use the Manifest.db to identify the hashed name of the included file, and copy out/rename the image to the appropriate name, without the examiner having to do that manually.

Features

This program will:

  1. Parse legacy (pre-iOS9) Notes files (but those are already plaintext, so not much to be gained)
  2. Parse iOS 9-15 Cloud Notes files
  3. ... decrypting notes if the password is known and the device passcode is not used
  4. ... generating CSV roll-ups of each account, folder, note, and embedded object within them
  5. ... rebuilding the notes as an HTML file to browse and see as they would be displayed on the phone
  6. ... amending the NoteStore.sqlite database to include plaintext and decompressed objects to interact with in other tools
  7. ... from iTunes logical backups, physical backups, single files, and directly from Mac versions
  8. ... displaying tables as actual tables and ripping the embedded images from the backup and putting them into a folder with the other output files for review
  9. ... identifying the CloudKit participants involved in any shared items.

Usage

Base

This program is run by Ruby on a command line, using either rake or ruby. The easiest use is to drop your exported NoteStore.sqlite into the same directory as this program and then run rake (which is the same as running ruby notes_cloud_ripper.rb --file NoteStore.sqlite).

If you are more comfortable with the command line, you can point the program anywhere you would like on your computer and specify the type of backup you are looking at, such as: ruby notes_cloud_ripper.rb --itunes-dir ~/.iTunes/backup1/ or ruby notes_cloud_ripper.rb --file ~/.iTunes/backup1/4f/4f98687d8ab0d6d1a371110e6b7300f6e465bef2. The benefit of pointing at full backups is this program can pull files out of them as needed, such as drawings and pictures.

Docker

Thanks to @jareware, if you have Docker installed already you can run this program as a docker container. This is a great way to ensure you will not run into any dependancy issues or have to have Ruby installed. Shell scripts have been provided in the docker_scripts folder which may help if they cover your use case. Each of these uses the present working directory to create the output folder.

  • linux_run_file.sh: This script will run the program on a NoteStore.sqlite file found in the present working directory (as if you ran -f NoteStore.sqlite).
  • mac_run_file.sh: This script will run the program on a NoteStore.sqlite file found in the present working directory (as if you ran -f NoteStore.sqlite).
  • mac_run_itunes.sh: This script will run the program on the local user's Mobile Backups(as if you used --itunes ~/Library/Application\ Support/MobileSync/Backup/[your backup]).
  • mac_run_notes.sh: This script will run the program on the local user's Apple Notes directory (as if you used --mac ~/Library/Group\ Containers/group.com.apple.notes).

If you are more experienced with Docker, you can use the base image with any of the below options the same as if you ran the program with Ruby. The basic command to use would be:

docker run --rm \
  -v [path to your data folder or file]:/data:ro \
  -v $(pwd)/output:/app/output \
  ghcr.io/threeplanetssoftware/apple_cloud_notes_parser \
  [your command line options]

As an example, to run a NoteStore.sqlite file that is in your current directory you would type:

docker run --rm \
  -v "$(pwd)":/data:ro \
  -v "$(pwd)"/output:/app/output \
  ghcr.io/threeplanetssoftware/apple_cloud_notes_parser \
  -f /data/NoteStore.sqlite --one-output-folder

Important Caveats:

  • While Docker can make things easier in some respects, it does so at the cost of additional complexity. It is harder to troubleshoot and adds more memory overhead. It is my hope that the Docker image helps some use this program, but the first troubleshooting step that will be recommended is to use Ruby directly to see if that fixes the issue.
  • The base image that is used for the Docker container is published by Ruby. It relies on a Debian base layer and as of today has multiple "vulnerabilities" identified on Docker (i.e. packages that are out of date). Use the Docker container at your own risk and if you are uncomfortable with it, feel free to clone this repository and use Ruby to run it, instead.
  • MacOS permissions lead to read errors trying to mount the Notes and iTunes backups from elsewhere in the user's home folder. As a result, the shell scripts create a temporary folder in the present working directory and copy the relevant files into it. This is an ugly hack which will chew up extra disk space and time to perform the copy. If you dislike this tradeoff, feel free to clone this repository and use Ruby to run it, instead.
  • Docker is a new feature for this program, there may be issues with the rollout.

Options

The options that are currently supported are:

  1. -f | --file FILE: Tells the program to look only at a specific file that is identified.
  2. -g | --one-output-folder: Tells the program to always overwrite the same folder [output]/notes_rip.
  3. -i | --itunes-dir DIRECTORY: Tells the program to look at an iTunes backup folder.
  4. -m | --mac DIRECTORY: Tells the program to look at a folder from a Mac.
  5. -o | --output-dir DIRECTORY: Changes the output folder from the default ./output to the specified one.
  6. -p | --physical DIRECTORY: Tells the program to look at a physical backup folder.
  7. -r | --retain-display-order: Tells the program to display the HTML output in the order Apple Notes displays it, not the database's order.
  8. -w | --password-file FILE: Tells the program which password list to use
  9. --show-password-successes: Tells the program to display to the console which passwords generated decrypts at the end.
  10. --range-start DATE: Set the start date of the date range to extract. Must use YYYY-MM-DD format, defaults to 1970-01-01.
  11. --range-end DATE: Set the end date of the date range to extract. Must use YYYY-MM-DD format, defaults to [tomorrow].
  12. --individual-files: Output individual HTML files for each note, organized in folders mirroring the Notes folder structure.
  13. --uuid: Use UUIDs in HTML output rather than local database IDs.
  14. -h | --help: Prints the usage information.

How It Works

iTunes backup (-i option)

For backups created with iTunes MobileSync, that include a wide range of hashed files inside of folders named after the filename, this program expects to be given the root folder of that backup. With that, it will compute the path to the NoteStore.sqlite file. If it exists, that file will be copied to the output directory and the copy, not the original, will be opened.

For example, if you had an iTunes backup located in /home/user/phone_rips/iphone/[deviceid]/ (Which means the Manifest.db is located at /home/whatever/phone_rips/iphone/[deviceid]/Manifest.db) you would run: ruby notes_cloud_ripper.rb -i /home/user/phone_rips/iphone/[deviceid]/

Physical backup (-p option)

For backups created with a full file system (or at least the /private directory) from your tool of choice. This program expects to be given the root folder of that backup. With that, it will compute the path to the NoteStore.sqlite file. If it exists, that file will be copied to the output directory and the copy, not the original, will be opened.

For example, if you had a physical backup located in /home/user/phone_rips/iphone/physical/ (Which means the phone's /private directory is located at /home/whatever/phone_rips/iphone/physical/private/) you would run: ruby notes_cloud_ripper.rb -p /home/user/phone_rips/iphone/physical

Single File (-f option)

For single file "backups", this program expects to be given the path of the NoteStore.sqlite file directly, although filename does not matter. If it exists, that file will be copied to the output directory and the copy, not the original, will be opened.

For example, if you had a NoteStore.sqlite file located in /home/user/phone_rips/iphone/files/NoteStore.sqlite you would run: ruby notes_cloud_ripper.rb -f /home/user/phone_rips/iphone/files/NoteStore.sqlite

Mac backup (-m option)

For backups created from the Notes app as installed on a Mac. This program expects to be given the group.com.apple.notes folder of that Mac. With that, it will compute the path to the NoteStore.sqlite file. If it exists, that file will be copied to the output directory and the copy, not the original, will be opened.

For example, if you were running this on data from a Mac used by 'Logitech' and had the full file system available, you would run: ruby notes_cloud_ripper.rb -m /Users/Logitech/Library/Group Containers/group.com.apple.notes/

Password (-w | --password-file FILE option)

For backups that may have encrypted notes within them, this option tells the program where to find its password list. This list should have one password per row and any passwords that correctly decrypt an encrypted note will be tried before the rest for future encrypted notes.

For example, if you were running this on data from a Mac used by 'Logitech,' had the full file system available, and wanted to use a file called "passwords.txt" you would run: ruby notes_cloud_ripper.rb -m /Users/Logitech/Library/Group Containers/group.com.apple.notes/ -w passwords.txt

Note: As of March 2021, all logging of passwords to the local debug_log.txt file and HTML output has been removed. If you need to see which passwords generated decrypted notes, use the --show-password-successes switch and read the console output after the run.

Note: As of iOS 16, users can use their device passcode instead of a spearate password within Notes. This program does not yet handle that case, it will simply fail to decrypt.

Date Range Extraction

Note: This feature is not intended to be robust. It does not smartly handle differences in timezones, nor convert to UTC. It is purely intended to help those with large Notes databases to better whittle down how much is processed.

The --range-start and --range-end switches allow the user to specify starting and ending dates for which notes to extract. By default, these will cover "all time" (i.e. 1970 through to tomorrow) so all notes should match, assuming system time hasn't been messed with. Officially these switches request the date format in "YYYY-MM-DD" format, but technically as long as Time.parse() can understand the format, it should work.

These selections are made on the ZICCLOUDSYNCINGOBJECT.ZMODIFIEDDATE1 field, which will capture any notes that have a modified date in that range. For example, if you wanted all notes modified after December 1, 2022, you could run: ruby notes_cloud_ripper.rb -f NoteStore.sqlite --range-start "2022-12-01". As another example, if you wanted to look at just the notes that were modified in June of 2022, you could run: ruby notes_cloud_ripper.rb -f NoteStore.sqlite --range-start "2022-06-01" --range-end "2022-07-01"

If you ever need to know what dates were used for a given backup, you can check the debug_log.txt file by looking for the line that has "Rip Notes" in it. For example: grep "Rip Notes" output/notes_rip/debug_log.txt

All Versions

Once the NoteStore file is opened, the program will create new AppleNotesAccount, AppleNotesFolder, and AppleNote objects based on the contents of that file. For each note, it takes the gzipped blob in the ZDATA field, gunzips it, and parses the protobuf that is inside. It will then add the plaintext from the protobuf of each note back into the NoteStore.sqlite file's ZICNOTEDATA table as a new column, ZPLAINTEXTDATA and create AppleNotesEmbeddedObject objects for each of the embedded objects it identifies.

Output

All of the output from this program will go into the output folder (it will be created if it doesn't exist), which defaults to [location of this program]/output. Within that folder, sub-folders will be created based on the current date and time, to the second. For example, if this program was run on December 17, 2019 at 10:24:28 local, the output for that run would be in [location of this program]/output/2019_12_17-10_24_28/. If the type of backup used has the original files referenced in attached media, this program will copy the file into the output directory, under [location of this program]/output/[date of run]/files, and beneath that following the file path on disk, relative to the Notes application folder.

If the -g option is passed, this program will always save its output into the [output location]/notes_rip folder, overwriting the contents each time. This may be useful for version control, or for people only ever parsing the same set of notes each time.

If the -r or --retain-display-order option is passed, then the HTML output will order the note entries under each folder at the top as Apple Notes displays them, not in the actual database order. This means that pinned notes will appear before unpinned notes and notes within the pinned and unpinned groups will be sorted according to modification time, newest to oldest. The order of note content at the bottom of the page will retain database order, by the note's ID (i.e. if Note 14 will come after Note 13 and before Note 15, regardless of which folders they are in). Soon the folder names themselves will also reflect the ordering as it appears in Apple Notes.

If the --individual-files option is passed, then the HTML output will be produced as individual files for each note, organized in folders that mirror the Notes folder hierarchy. This can be useful for comparing successive exports to see which notes have changed.

If the --uuid option is passed, then the HTML output will refer to notes by their UUID (taken from ZICCLOUDSYNCINGOBJECT.ZIDENTIFIER) rather than the integer ID used in the local database. These UUIDs should be consistent across devices synced with iCloud, whereas the integer IDs will be specific to each device.

This program will produce four CSV files summarizing the information stored in [location of this program]/output/[date of run]/csv: note_store_accounts.csv, note_store_embedded_objects.csv, note_store_folders.csv, and note_store_notes.sqlite. It will also produce an HTML dump of the notes to reflect the text and table formatting which may be meaningful in [location of this program]/output/[date of run]/html. Finally, it will produce a JSON dump for each of the NoteStore files, summarizing the accounts, folders, and notes within that NoteStore file.

Because Apple devices often have more than one version of Notes, it is important to note (pun intended) that all of the output is suffixed by a number, starting at 1, to identify which of the backups it corresponds to. In all cases where more than one is found, care is taken to produce output that assigns the suffix of 1 for the modern version, and the suffix of 2 for the legacy version.

JSON Format

The JSON file's overall output is what is generated by the AppleNoteStore class, as noted below.

{
  "version": "[integer listing iOS version]",
  "file_path": "[filepath to OUTPUT database]",
  "backup_type": "[integer indicating the type of backup]",
  "html": "[full HTML goes here]",
  "accounts": {
    "[account z_pk]": "[AppleNotesAccount object JSON]"
  },
  "cloudkit_participants": {
    "[cloudkit identifier]": "[AppleCloudKitShareParticipant object JSON]"
  },
  "folders": {
    "[folder z_pk]": "[AppleNotesFolder object JSON]"
  },
  "notes": {
    "[note id]": "[AppleNote object JSON]"
  }
}

The JSON output of AppleNotesAccount is as follows.

{
  "primary_key": "[integer account z_pk]",
  "name": "[account name]",
  "identifier": "[account ZIDENTIFIER]",
  "cloudkit_identifier": "[account Cloudkit identifier]",
  "cloudkit_last_modified_device": "[account last modified device]",
  "html": "[HTML generated for the specific account goes here]"
}

The JSON output of AppleCloudKitShareParticipant is as follows.

{
  "email": "[user's email, if available]",
  "record_id": "cloudkit identifier",
  "first_name": "[user's first name, if available]",
  "last_name": "[user's last name, if available]",
  "middle_name": "[user's middle name, if available]",
  "name_prefix": "[user's name prefix, if available]",
  "name_suffix": "[user's name suffix, if available]",
  "name_phonetic": "[user's name pronunciation, if available]",
  "phone": "[user's phone number, if available]"
}

The JSON output of AppleNotesFolder is as follows.

{
  "primary_key": "[integer folder z_pk]",
  "uuid": "[folder uuid from ZICCLOUDSYNCINGOBJECT.ZIDENTIFIER]",
  "name": "[folder name]",
  "account_id": "[integer z_pk for the account this belongs to]",
  "account": "[account name]",
  "parent_folder_id": "[integer of parent folder's z_pk, if applicable]",
  "child_folders": {
    "[folder z_pk]": "[AppleNotesFolder object JSON]"
  },
  "html": "[folder HTML output]",
  "query": "[query string if folder is a smart folder]"
}

The JSON output of AppleNote is as follows.

{
  "account_key": "[z_pk of the account]",
  "account": "[account name]",
  "folder_key": "[z_pk of the folder]",
  "folder": "[Folder name]",
  "note_id": "[note ID]",
  "uuid": "[note uuid from ZICCLOUDSYNCINGOBJECT.ZIDENTIFIER]",
  "primary_key": "[z_pk of the note]",
  "creation_time": "[creation time in YYYY-MM-DD HH:MM:SS TZ format]",
  "modify_time": "[modify time in YYYY-MM-DD HH:MM:SS TZ format]",
  "cloudkit_creator_id": "[cloudkit ID of the note creator, if applicable]",
  "cloudkit_modifier_id": "[cloudkit ID of the last note modifier, if applicable]",
  "cloudkit_last_modified_device": "[last modified device, according to CloudKit]",
  "is_pinned": "[boolean, whether pinned or not]",
  "is_password_protected": "[boolean, whether password protected or not]",
  "title": "[Note title]",
  "plaintext": "[plaintext of the note",
  "html": "[HTML of the note]",
  "note_proto": "[NoteStoreProto dump of the decoded protobuf]",
  "embedded_objects": [
    "[Array of AppleNotesEmbeddedObject object JSON]"
  ],
  "hashtags": [
    "#Test"
  ],
  "mentions": [
    "@FirstName [CloudKit Email]"
  ]
}

The JSON output of AppleNotesEmbeddedObject is as follows.

{
  "primary_key": "[z_pk of the object]",
  "parent_primary_key": "[z_pk of the object's parent, if applicable]",
  "note_id": "[note ID]",
  "uuid": "[ZIDENTIFIER of the object]",
  "type": "[ZTYPEUTI of the object]",
  "filename": "[filename of the object, if applicable]",
  "filepath": "[filepath of the object, including filename, if applicable]",
  "backup_location": "[Filepath of the original backup location, if applicable]",
  "user_title": "[The alternate filename given by the user, if applicable]",
  "is_password_protected": "[boolean, whether password protected or not]",
  "html": "[generated HTML for the object]",
  "thumbnails": [
    "[Array of AppleNotesEmbeddedObject object JSON, if applicable]"
  ],
  "child_objects": [
    "[Array of AppleNotesEmbeddedObject object JSON, if applicable]"
  ],
  "table": [
    [
      "row 0", "column 0",
      "row 0", "column 1... etc"
    ]
  ],
  "url": "[url, if applicable]"
}

Requirements

Ruby Version

This program requires Ruby version 3.0 or later.

Gems

This program requires the following Ruby gems which can be installed by running bundle install or gem install [gemname]:

  1. fileutils
  2. google-protobuf
  3. sqlite3
  4. zlib
  5. openssl
  6. aes_key_wrap
  7. keyed_archive
  8. nokogiri
  9. cgi (0.3.3 or newer)

Installation

Below are instructions, generally preferring the command line, for each of Linux, Mac, and Windows. The user can choose to use Git if they want to be able to keep up with changes, or just download the tool once, you do not need to do both. On each OS, you will want to:

  1. Install Ruby (at least version 3.0), its development headers, and bundler if not already installed.
  2. Install development headers for SQLite3 if not already installed.
  3. Get this code
    1. Clone this repository with Git or
    2. Download the Zip file and unzip it
  4. Enter the repository's directory.
  5. Use bundler to install the required gems.
  6. Run the program (see Usage section)!

Debian-based Linux (Debian, Ubuntu, Mint, etc)

With Git (If you want to stay up to date)

sudo apt-get install build-essential libsqlite3-dev zlib1g-dev git ruby-full ruby-bundler
git clone https://github.com/threeplanetssoftware/apple_cloud_notes_parser.git
cd apple_cloud_notes_parser
bundle install

Without Git (If you want to download it every now and then)

sudo apt-get install build-essential libsqlite3-dev zlib1g-dev git ruby-full ruby-bundler
curl https://codeload.github.com/threeplanetssoftware/apple_cloud_notes_parser/zip/master -o apple_cloud_notes_parser.zip
unzip apple_cloud_notes_parser.zip
cd apple_cloud_notes_parser-master
bundle install

Red Hat-based Linux (Red Hat, CentOS, etc)

With Git (If you want to stay up to date)

sudo yum groupinstall "Development Tools" 
sudo yum install sqlite sqlite-devel zlib zlib-devel openssl openssl-devel ruby ruby-devel rubygem-bundler
git clone https://github.com/threeplanetssoftware/apple_cloud_notes_parser.git
cd apple_cloud_notes_parser
bundle install
sudo gem pristine sqlite3 zlib openssl aes_key_wrap keyed_archive

Without Git (If you want to download it every now and then)

sudo yum groupinstall "Development Tools" 
sudo yum install sqlite sqlite-devel zlib zlib-devel openssl openssl-devel ruby ruby-devel rubygem-bundler
curl https://codeload.github.com/threeplanetssoftware/apple_cloud_notes_parser/zip/master -o apple_cloud_notes_parser.zip
unzip apple_cloud_notes_parser.zip
cd apple_cloud_notes_parser-master
bundle install
sudo gem pristine sqlite3 zlib openssl aes_key_wrap keyed_archive

macOS

With Git (If you want to stay up to date)

git clone https://github.com/threeplanetssoftware/apple_cloud_notes_parser.git
cd apple_cloud_notes_parser
bundle install

Without Git (If you want to download it every now and then)

curl https://codeload.github.com/threeplanetssoftware/apple_cloud_notes_parser/zip/master -o apple_cloud_notes_parser.zip
unzip apple_cloud_notes_parser.zip
cd apple_cloud_notes_parser-master
bundle install

Windows

  1. Download the 2.7.2 64-bit RubyInstaller with DevKit
  2. Run RubyInstaller using default settings.
  3. Download the latest SQLite amalgamation souce code and 64-bit SQLite Precompiled DLL
  4. Install SQLite
    1. Create a folder C:\sqlite
    2. Unzip the source code into C:\sqlite (you should now have C:\sqlite\sqlite3.c and C:\sqlite\sqlite.h, among others)
    3. Unzip the DLL into C:\sqlite (you should now have C:\sqlite\sqlite3.dll, among others)
  5. Download this Apple Cloud Notes Parser as a zip archive
  6. Unzip the Zip archive
  7. Launch a command prompt window with "Start a command prompt wqith ruby" from the Start menu and navigate to where you unzipped the archive
  8. Execute the following commands (these set the PATH so SQLite files can be found install SQLite's Gem specifically pointing to them, and then installs the rest of the gems):
powershell
$env:Path += ";C:\sqlite"
[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\sqlite", "User")
gem install sqlite3 --platform=ruby -- --with-sqlite-3-dir=C:/sqlite --with-sqlite-3-include=C:/sqlite
bundle install

Folder Structure

For reference, the structure of this program is as follows:

apple_cloud_notes_parser
  |
  |-docker_scripts
  |  |
  |  |-linux_run_file.sh: Execute the docker version on NoteStore.sqlite in the present working directory
  |  |-mac_run_file.sh: Execute the docker version on NoteStore.sqlite in the present working directory
  |  |-mac_run_itunes.sh: Execute the docker version on each of the local Mac user's mobile backups
  |  |-mac_run_notes.sh: Execute the docker version on the local Mac user's Notes folder
  |  
  |-lib
  |  |
  |  |-notestore_pb.rb: Protobuf representation generated with protoc
  |  |-Apple\*.rb: Ruby classes dealing with various aspects of Notes
  |
  |-output (created after run)
  |  |
  |  |-[folders for each date/time run]
  |     |
  |     |-csv: This folder holds the CSV output
  |     |-debug_log.txt: A more verbose log to assist with debugging
  |     |-files: This folder holds files copied out of the backup, such as pictures
  |     |-html: This folder holds the generated HTML copy of the Notestore
  |     |-json: This folder holds the generated JSON summary of the Notestore
  |     |-Manifest.db: If run on an iTunes backup, this is a copy of the Manifest.db
  |     |-NoteStore.sqlite: If run on a modern version, this copy of the target file will include plaintext versions of the Notes
  |     |-notes.sqlite: If run on a legacy version, this copy is just a copy for ease of use
  |
  |-.gitignore
  |-.travis.yml
  |-Dockerfile
  |-Gemfile
  |-LICENSE
  |-README.md
  |-Rakefile
  |-notes_cloud_ripper.rb: The main program itself

FAQ

Why do I get a "No such column" error?

Example: /var/lib/gems/2.3.0/gems/sqlite3-1.4.1/lib/sqlite3/database.rb:147:in 'initialize': no such column: ZICCLOUDSYNCINGOBJECT.ZSERVERRECORDDATA (SQLite3::SQLException)

Apple changed the format of its Notes database in different versions of iOS. While the supported versions should be supported, interesting cases may come up. Please open an issue and include the stack trace and the following information:

  • iOS version (including any versions it may have upgraded from)
  • The results of SELECT name,sql FROM sqlite_master WHERE type="table" when the database is open in sqlitebrowser (or your editor of choice). This can be in any columned format (Excel, CSV, SQL, etc)
  • If possible, the database file directly (I can receive it through other means if it needs to stay confidential). If this is possible, the above results are not needed.

Why Ruby instead of Python or Perl?

Programming languages are like human languages, there are many and which you choose (for those with multiple) can largely be a personal preference, assuming mutual intelligibility. I chose Ruby as the previous Perl code was a nice little script, but I wanted a bit more substance behind with with solid object oriented programming principals. For those new to Ruby, hopefully these classes will give you an idea of what Ruby has to offer and spark an interest in trying a new language.

Known Bugs

Acknowledgements

  • MildSunrise's protobuf-inspector drove most of my analysis into the Notes protobufs.
  • Previous work by dunhamsteve proved invaluable to finally understanding the embedded table aspects.

apple_cloud_notes_parser's People

Contributors

ggilder avatar gui avatar mirnovov avatar thesnarky1 avatar threeplanetssoftware avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

apple_cloud_notes_parser's Issues

long sketches are not exported

If you have a note that's a very very long sketch (like, takes dozens of full page scrolls to get to the end), in the html export it shows just the first tiny bit of it.

For example [in this case the note is by my 4 year old], the exported image SHOULD have all of this content.

But instead, you get this. And yes, that's where it cuts off - there is nothing beyond that.

This may be a Notes bug, as if you try to print to pdf a note with a long image, it only exports the first "page" or so.

org.openxmlformats.wordprocessingml.document is unrecognized ZTYPEUTI

Two issues here. First, I'd really love #16 to be solved in some better way if possible - I don't like seeing those errors every single time I run.

More relevantly to this issue, I'm getting

org.openxmlformats.wordprocessingml.document is unrecognized ZTYPEUTI

Full output:

Starting Apple Notes Parser at Sat Jul  9 20:09:47 2022
Storing the results in /Users/dmd/Dropbox/bk/AppleNotes/2022_07_09-20_09_47

Created a new AppleBackup from Mac backup: /Users/dmd/Library/Group Containers/group.com.apple.notes/
Guessed Notes Version: 15
Skipping Note ID 19 due to a missing folder or account, check the debug log for more details.
Skipping Note ID 25 due to a missing folder or account, check the debug log for more details.
Skipping Note ID 1231 due to a missing folder or account, check the debug log for more details.
Skipping Note ID 1232 due to a missing folder or account, check the debug log for more details.
Skipping Note ID 1288 due to a missing folder or account, check the debug log for more details.
Skipping Note ID 1311 due to a missing folder or account, check the debug log for more details.
Skipping Note ID 1403 due to a missing folder or account, check the debug log for more details.
Skipping Note ID 1562 due to a missing folder or account, check the debug log for more details.
Skipping Note ID 1621 due to a missing folder or account, check the debug log for more details.
Skipping Note ID 1638 due to a missing folder or account, check the debug log for more details.
Skipping Note ID 1642 due to a missing folder or account, check the debug log for more details.
org.openxmlformats.wordprocessingml.document is unrecognized ZTYPEUTI, please submit a bug report to this project's GitHub repo to report this: https://github.com/threeplanetssoftware/apple_cloud_notes_parser/issues
Updated AppleNoteStore object with 151 AppleNotes in 10 folders belonging to 1 accounts.
Adding the ZICNOTEDATA.ZPLAINTEXT and ZICNOTEDATA.ZDECOMPRESSEDDATA columns, this takes a few seconds

Tags

iOS 15 added tags to Notes. They behave like embedded objects, need to get them added.

By default, output directory maybe shouldn't have a timestamp

Probably a matter of opinion, but I don't think that the default behavior of the script should be to create a nested directory with a timestamp. I think this behavior is less conventional; it's more conducive to debugging this project, but not for everyday use.

I'm especially thinking of relying on both Time Machine and git to handle versioning for me. So the path must stay the same.

If I use this script for backups and versioning, even with the -o flag, then I would have to do a bit of massaging (granted, not very complicated) to normalize the paths.

If the default were to be changed, then it would be trivial to specify a -o ./output/$(date -Iseconds) or to write a script wrapper to get back to the original behavior.

Crash in AppleBackup.back_up_file

I'm running ruby notes_cloud_ripper.rb --mac ~/Library/Group\ Containers/group.com.apple.notes/ for the first time and getting:

โฏ /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/3.1.0/pathname.rb:353:in `initialize': no implicit conversion of nil into String (TypeError)
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/3.1.0/pathname.rb:353:in `new'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/3.1.0/pathname.rb:353:in `+'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleBackup.rb:122:in `back_up_file'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNotesEmbeddedPublicJpeg.rb:31:in `initialize'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:211:in `new'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:211:in `block (2 levels) in replace_embedded_objects'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:204:in `block (2 levels) in execute'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/resultset.rb:134:in `each'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:203:in `block in execute'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:156:in `prepare'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:198:in `execute'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:173:in `block in replace_embedded_objects'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:153:in `each'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:153:in `replace_embedded_objects'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:114:in `initialize'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNoteStore.rb:615:in `new'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNoteStore.rb:615:in `block in rip_note'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:204:in `block (2 levels) in execute'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/resultset.rb:134:in `each'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:203:in `block in execute'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:156:in `prepare'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:198:in `execute'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNoteStore.rb:605:in `rip_note'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNoteStore.rb:507:in `block in rip_notes'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:204:in `block (2 levels) in execute'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/resultset.rb:134:in `each'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:203:in `block in execute'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:156:in `prepare'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:198:in `execute'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNoteStore.rb:506:in `rip_notes'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNoteStore.rb:193:in `rip_all_objects'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleBackup.rb:159:in `block in rip_notes'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleBackup.rb:157:in `each'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleBackup.rb:157:in `rip_notes'
	from notes_cloud_ripper.rb:128:in `<main>'

Looking at the logs, it seems the process was able to work through a bunch of notes and Embedded Object of type public.jpeg but it seems to crash on one of them:

D, [2022-08-01T11:41:21.000382 #54006] DEBUG -- : AppleNote: Note 903 replacing attachment 7513D337-3C2E-4C7F-B6D7-F379BF72171E
D, [2022-08-01T11:41:21.000402 #54006] DEBUG -- : Note 903: Created a new Embedded Object of type public.jpeg

Any idea what could be wrong?

Getting some issue parsing table

Starting Apple Notes Parser at Thu Sep  8 22:57:15 2022
Storing the results in ./output/notes_rip

Created a new AppleBackup from single file: NoteStore.sqlite
Guessed Notes Version: 15
/Users/m1/parser/lib/AppleNotesEmbeddedTable.rb:145:in `block (2 levels) in parse_cell_columns': no implicit conversion from nil to integer (TypeError)
	from /Users/m1/parser/lib/AppleNotesEmbeddedTable.rb:139:in `each'
	from /Users/m1/parser/lib/AppleNotesEmbeddedTable.rb:139:in `block in parse_cell_columns'
	from /Users/m1/parser/lib/AppleNotesEmbeddedTable.rb:134:in `each'
	from /Users/m1/parser/lib/AppleNotesEmbeddedTable.rb:134:in `parse_cell_columns'
	from /Users/m1/parser/lib/AppleNotesEmbeddedTable.rb:185:in `block in parse_table'
	from /Users/m1/parser/lib/AppleNotesEmbeddedTable.rb:166:in `each'
	from /Users/m1/parser/lib/AppleNotesEmbeddedTable.rb:166:in `parse_table'
	from /Users/m1/parser/lib/AppleNotesEmbeddedTable.rb:297:in `block in rebuild_table'
	from /Users/m1/parser/lib/AppleNotesEmbeddedTable.rb:295:in `each'
	from /Users/m1/parser/lib/AppleNotesEmbeddedTable.rb:295:in `rebuild_table'
	from /Users/m1/parser/lib/AppleNotesEmbeddedTable.rb:49:in `initialize'
	from /Users/m1/parser/lib/AppleNotesEmbeddedObject.rb:353:in `new'
	from /Users/m1/parser/lib/AppleNotesEmbeddedObject.rb:353:in `block (2 levels) in generate_embedded_objects'

no such table: ZACCOUNT (SQLite3::SQLException)

Unfortunately i receive the following message when running ruby notes_cloud_ripper.rb --file path/to/NotesV7.storedata:

Starting Apple Notes Parser at Sat Jan 23 22:12:56 2021
Storing the results in ./output/2021_01_23-22_12_56

Created a new AppleBackup from single file: /Users/iwanuschka/Desktop/apple_cloud_notes_parser/output/2021_01_23-22_12_42/notes.sqlite
Guessed Notes Version: 8
Traceback (most recent call last):
	9: from notes_cloud_ripper.rb:122:in `<main>'
	8: from /Users/iwanuschka/Desktop/apple_cloud_notes_parser/lib/AppleBackup.rb:124:in `rip_notes'
	7: from /Users/iwanuschka/Desktop/apple_cloud_notes_parser/lib/AppleBackup.rb:124:in `each'
	6: from /Users/iwanuschka/Desktop/apple_cloud_notes_parser/lib/AppleBackup.rb:126:in `block in rip_notes'
	5: from /Users/iwanuschka/Desktop/apple_cloud_notes_parser/lib/AppleNoteStore.rb:185:in `rip_all_objects'
	4: from /Users/iwanuschka/Desktop/apple_cloud_notes_parser/lib/AppleNoteStore.rb:324:in `rip_accounts'
	3: from /Users/iwanuschka/.rvm/gems/ruby-2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
	2: from /Users/iwanuschka/.rvm/gems/ruby-2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:147:in `prepare'
	1: from /Users/iwanuschka/.rvm/gems/ruby-2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:147:in `new'
/Users/iwanuschka/.rvm/gems/ruby-2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:147:in `initialize': no such table: ZACCOUNT (SQLite3::SQLException)

My system:

  • Mac OS 11.1
  • ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-darwin20]
  • rvm 1.29.12 (latest) by Michal Papis, Piotr Kuczynski, Wayne E. Seguin [https://rvm.io]

I reinstalled ruby including (?) openssl like

rvm reinstall ruby-2.6.0 --with-openssl-dir=/usr/local/opt/openssl
rvm reload

Hope you can help me because i just lost all my notes :/ The data seems to be still there but cannot be retrieved correctly.

how to figure out failing note id

Skipping Note ID 19 due to a missing folder or account, check the debug log for more details.
Skipping Note ID 25 due to a missing folder or account, check the debug log for more details.

Can you suggest a way to determine which notes these are? (Maybe a series of sqlite commands to enter?)

(Also, while you're looking at this - can you @threeplanetssoftware contact me [email protected] by email, I have an unrelated question to ask you and can't find your email.)

Pinned notes and folders order

It's possible to Pin note and it's possible to rearrange folders order.
I assume this information is somewhere in sqlite db. Would it be possible to add this to the library?

Missing `filename` when replacing embedded objects

There are several of these filepaths with missing filenames: Accounts/BBF62EC9-7366-451B-987A-745A1CA06D54/Media//.

As a workaround I bypassed the backup in AppleNotesEmbeddedPublicJpeg.rb with unless @filename.nil?.

Traceback (most recent call last):
	35: from notes_cloud_ripper.rb:128:in `<main>'
	34: from /tmp/apple_cloud_notes_parser/lib/AppleBackup.rb:157:in `rip_notes'
	33: from /tmp/apple_cloud_notes_parser/lib/AppleBackup.rb:157:in `each'
	32: from /tmp/apple_cloud_notes_parser/lib/AppleBackup.rb:159:in `block in rip_notes'
	31: from /tmp/apple_cloud_notes_parser/lib/AppleNoteStore.rb:193:in `rip_all_objects'
	30: from /tmp/apple_cloud_notes_parser/lib/AppleNoteStore.rb:506:in `rip_notes'
	29: from /tmp/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
	28: from /tmp/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:151:in `prepare'
	27: from /tmp/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:198:in `block in execute'
	26: from /tmp/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/sqlite3-1.4.2/lib/sqlite3/resultset.rb:134:in `each'
	25: from /tmp/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:199:in `block (2 levels) in execute'
	24: from /tmp/apple_cloud_notes_parser/lib/AppleNoteStore.rb:507:in `block in rip_notes'
	23: from /tmp/apple_cloud_notes_parser/lib/AppleNoteStore.rb:605:in `rip_note'
	22: from /tmp/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
	21: from /tmp/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:151:in `prepare'
	20: from /tmp/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:198:in `block in execute'
	19: from /tmp/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/sqlite3-1.4.2/lib/sqlite3/resultset.rb:134:in `each'
	18: from /tmp/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:199:in `block (2 levels) in execute'
	17: from /tmp/apple_cloud_notes_parser/lib/AppleNoteStore.rb:615:in `block in rip_note'
	16: from /tmp/apple_cloud_notes_parser/lib/AppleNoteStore.rb:615:in `new'
	15: from /tmp/apple_cloud_notes_parser/lib/AppleNote.rb:111:in `initialize'
	14: from /tmp/apple_cloud_notes_parser/lib/AppleNote.rb:150:in `replace_embedded_objects'
	13: from /tmp/apple_cloud_notes_parser/lib/AppleNote.rb:150:in `each'
	12: from /tmp/apple_cloud_notes_parser/lib/AppleNote.rb:170:in `block in replace_embedded_objects'
	11: from /tmp/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
	10: from /tmp/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:151:in `prepare'
	 9: from /tmp/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:198:in `block in execute'
	 8: from /tmp/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/sqlite3-1.4.2/lib/sqlite3/resultset.rb:134:in `each'
	 7: from /tmp/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:199:in `block (2 levels) in execute'
	 6: from /tmp/apple_cloud_notes_parser/lib/AppleNote.rb:208:in `block (2 levels) in replace_embedded_objects'
	 5: from /tmp/apple_cloud_notes_parser/lib/AppleNote.rb:208:in `new'
	 4: from /tmp/apple_cloud_notes_parser/lib/AppleNotesEmbeddedPublicJpeg.rb:31:in `initialize'
	 3: from /tmp/apple_cloud_notes_parser/lib/AppleBackup.rb:122:in `back_up_file'
	 2: from /tmp/.rbenv/versions/2.7.3/lib/ruby/2.7.0/pathname.rb:350:in `+'
	 1: from /tmp/.rbenv/versions/2.7.3/lib/ruby/2.7.0/pathname.rb:350:in `new'
/tmp/.rbenv/versions/2.7.3/lib/ruby/2.7.0/pathname.rb:350:in `initialize': no implicit conversion of nil into String (TypeError)

Update Windows instructions to use a newer version of rubyinstaller

Hi, thanks for an impressive tool!

A heads up that rubyinstaller-devkit-2.6.5-1-x64 - which you link to in your Windows installation instructions - has issues with PGP keys which causes the MSYS2 part of the installation to fail and means that gem install sqlite3 doesn't work. See oneclick/rubyinstaller2#184

I ran your same instructions using rubyinstaller-devkit-2.7.2-1-x64 and that worked fine. You would probably need to test it yourself before updating the instructions, but thought I'd share the info.

No such file or directory?


Starting Apple Notes Parser at Thu Nov  5 20:32:29 2020
Storing the results in /Users/dmd/Dropbox/bk/AppleNotes/2020_11_05-20_32_29

Created a new AppleBackup from Mac backup: /Users/dmd/Library/Group Containers/group.com.apple.notes/
Guessed Notes Version: 13
Skipping Note ID 19 due to a missing folder or account, check the debug log for more details.
Skipping Note ID 25 due to a missing folder or account, check the debug log for more details.
Traceback (most recent call last):
	51: from notes_cloud_ripper.rb:122:in `<main>'
	50: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleBackup.rb:124:in `rip_notes'
	49: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleBackup.rb:124:in `each'
	48: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleBackup.rb:126:in `block in rip_notes'
	47: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:187:in `rip_all_objects'
	46: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:487:in `rip_notes'
	45: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
	44: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:151:in `prepare'
	43: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:198:in `block in execute'
	42: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/resultset.rb:134:in `each'
	41: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:199:in `block (2 levels) in execute'
	40: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:488:in `block in rip_notes'
	39: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:573:in `rip_note'
	38: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
	37: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:151:in `prepare'
	36: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:198:in `block in execute'
	35: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/resultset.rb:134:in `each'
	34: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:199:in `block (2 levels) in execute'
	33: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:583:in `block in rip_note'
	32: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:583:in `new'
	31: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNote.rb:106:in `initialize'
	30: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNote.rb:138:in `replace_embedded_objects'
	29: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNote.rb:138:in `each'
	28: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNote.rb:144:in `block in replace_embedded_objects'
	27: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
	26: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:151:in `prepare'
	25: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:198:in `block in execute'
	24: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/resultset.rb:134:in `each'
	23: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:199:in `block (2 levels) in execute'
	22: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNote.rb:177:in `block (2 levels) in replace_embedded_objects'
	21: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNote.rb:177:in `new'
	20: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNotesEmbeddedGallery.rb:17:in `initialize'
	19: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNotesEmbeddedObject.rb:51:in `initialize'
	18: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNotesEmbeddedObject.rb:110:in `search_and_add_thumbnails'
	17: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
	16: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:151:in `prepare'
	15: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:198:in `block in execute'
	14: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/resultset.rb:134:in `each'
	13: from /Library/Ruby/Gems/2.6.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:199:in `block (2 levels) in execute'
	12: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNotesEmbeddedObject.rb:115:in `block in search_and_add_thumbnails'
	11: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNotesEmbeddedObject.rb:115:in `new'
	10: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNotesEmbeddedThumbnail.rb:33:in `initialize'
	 9: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleBackup.rb:103:in `back_up_file'
	 8: from /Library/Ruby/Gems/2.6.0/gems/fileutils-1.4.1/lib/fileutils.rb:429:in `cp'
	 7: from /Library/Ruby/Gems/2.6.0/gems/fileutils-1.4.1/lib/fileutils.rb:1586:in `fu_each_src_dest'
	 6: from /Library/Ruby/Gems/2.6.0/gems/fileutils-1.4.1/lib/fileutils.rb:1604:in `fu_each_src_dest0'
	 5: from /Library/Ruby/Gems/2.6.0/gems/fileutils-1.4.1/lib/fileutils.rb:1588:in `block in fu_each_src_dest'
	 4: from /Library/Ruby/Gems/2.6.0/gems/fileutils-1.4.1/lib/fileutils.rb:430:in `block in cp'
	 3: from /Library/Ruby/Gems/2.6.0/gems/fileutils-1.4.1/lib/fileutils.rb:511:in `copy_file'
	 2: from /Library/Ruby/Gems/2.6.0/gems/fileutils-1.4.1/lib/fileutils.rb:1413:in `copy_file'
	 1: from /Library/Ruby/Gems/2.6.0/gems/fileutils-1.4.1/lib/fileutils.rb:1413:in `open'
/Library/Ruby/Gems/2.6.0/gems/fileutils-1.4.1/lib/fileutils.rb:1413:in `initialize': No such file or directory @ rb_sysopen - /Users/dmd/Library/Group Containers/group.com.apple.notes/Accounts/5D743F4B-4367-4797-8838-B2E6F2971661/Previews/0E395B5A-71C1-464F-9AF6-1F40106B9B5E-1-192x119-0.jpg (Errno::ENOENT)

Generates empty .html and no csv (undefined method `name' for nil:NilClass and undefined method `primary_key' for nil:NilClass)

mshibo@mshibo ~/apple_cloud_notes_parser $ ruby notes_cloud_ripper.rb --file NoteStore.sqlite 

Starting Apple Notes Parser at Thu May 28 06:37:21 2020
Storing the results in ./output/2020_05_28-06_37_21

Created a new AppleBackup from single file: NoteStore.sqlite
Guessed Notes Version: 13
com.compuserve.gif is unrecognized, please submit a bug report to this project's GitHub repo to report this: https://github.com/threeplanetssoftware/apple_cloud_notes_parser/issues
com.compuserve.gif is unrecognized, please submit a bug report to this project's GitHub repo to report this: https://github.com/threeplanetssoftware/apple_cloud_notes_parser/issues
com.apple.drawing is unrecognized, please submit a bug report to this project's GitHub repo to report this: https://github.com/threeplanetssoftware/apple_cloud_notes_parser/issues
Updated AppleNoteStore object with 940 AppleNotes in 3 folders belonging to 1 accounts.
Adding the ZICNOTEDATA.ZPLAINTEXT and ZICNOTEDATA.ZDECOMPRESSEDDATA columns, this takes a few seconds
/home/mshibo/apple_cloud_notes_parser/lib/AppleNote.rb:353:in `generate_html': undefined method `name' for nil:NilClass (NoMethodError)
	from /home/mshibo/apple_cloud_notes_parser/lib/AppleNoteStore.rb:532:in `block in generate_html'
	from /home/mshibo/apple_cloud_notes_parser/lib/AppleNoteStore.rb:530:in `each'
	from /home/mshibo/apple_cloud_notes_parser/lib/AppleNoteStore.rb:530:in `generate_html'
	from notes_cloud_ripper.rb:127:in `block (2 levels) in <main>'
	from notes_cloud_ripper.rb:126:in `open'
	from notes_cloud_ripper.rb:126:in `block in <main>'
	from notes_cloud_ripper.rb:123:in `each'
	from notes_cloud_ripper.rb:123:in `<main>'

Script begins to work normally, then NoMethodError

tl;dr -- I'm running ruby notes_cloud_ripper.rb -f NoteStore.sqlite on Ubuntu 20.04, and the first few steps appear to work, but then I get a (mysterious, to me) NoMethodError.

Traceback screenshot included.

I have no idea where to go from here, and am wondering if this is a bug or just my own error(s).

Please let me know if there is other helpful information I can provide.

Thank you.

Screen Shot 2022-07-06 at 00 10 48

block in generate_html_text: undefined method generate_html for nil:NilClass (NoMethodError)

Getting the error in the title when I try to run your app against a NoteStore.sqlite file recovered from a Time Machine backup of a Mac running macOS 10.15.3. (The backup is from October 2019 so not sure what version was in use then).

Command I ran: ruby notes_cloud_ripper.rb -f /Users/tom/Downloads/NoteStore.sqlite

Prior to running this I ran bundle install and that completed successfully.

Any ideas? Full output:

Guessed Notes Version: 13
com.apple.drawing is unrecognized, please submit a bug report to this project's GitHub repo to report this: https://github.com/threeplanetssoftware/apple_cloud_notes_parser/issues
com.apple.drawing is unrecognized, please submit a bug report to this project's GitHub repo to report this: https://github.com/threeplanetssoftware/apple_cloud_notes_parser/issues
Updated AppleNoteStore object with 361 AppleNotes in 2 folders belonging to 1 accounts.
Adding the ZICNOTEDATA.ZPLAINTEXT and ZICNOTEDATA.ZDECOMPRESSEDDATA columns, this takes a few seconds
Traceback (most recent call last):
	11: from notes_cloud_ripper.rb:109:in `<main>'
	10: from notes_cloud_ripper.rb:109:in `each'
	 9: from notes_cloud_ripper.rb:112:in `block in <main>'
	 8: from notes_cloud_ripper.rb:112:in `open'
	 7: from notes_cloud_ripper.rb:113:in `block (2 levels) in <main>'
	 6: from /Users/tom/Documents/apple_cloud_notes_parser/lib/AppleNoteStore.rb:530:in `generate_html'
	 5: from /Users/tom/Documents/apple_cloud_notes_parser/lib/AppleNoteStore.rb:530:in `each'
	 4: from /Users/tom/Documents/apple_cloud_notes_parser/lib/AppleNoteStore.rb:532:in `block in generate_html'
	 3: from /Users/tom/Documents/apple_cloud_notes_parser/lib/AppleNote.rb:344:in `generate_html'
	 2: from /Users/tom/Documents/apple_cloud_notes_parser/lib/AppleNote.rb:372:in `generate_html_text'
	 1: from /Users/tom/Documents/apple_cloud_notes_parser/lib/AppleNote.rb:372:in `each'
/Users/tom/Documents/apple_cloud_notes_parser/lib/AppleNote.rb:377:in `block in generate_html_text': undefined method `generate_html' for nil:NilClass (NoMethodError)

public.data is unrecognized

I get an error when parsing a mac Notes db:
public.data is unrecognized, please submit a bug report to this project's GitHub repo to report this: https://github.com/threeplanetssoftware/apple_cloud_notes_parser/issues

As mentioned in:
Originally posted by @threeplanetssoftware in #8 (comment)

Any chance you would help me recreate a public.data object? Just understanding what you put into the note and how would be enough.

I grepped the .csv output and found the note and attachment with type public.data.

It shows in Notes like this:
image

But when I click it, it's actually a PNG file.

My original steps were:

  1. Install Outline.ws version 3.21.2 -- they have a 14 day trial, but isn't needed. See next set of steps.
  2. Create a note in Outline.ws with an image
  3. Copy the the image from Outline.ws and paste it into Notes
  4. In Notes, it will have the above attachment symbol.

I found you can get a almost similar attachment symbol, by doing the following, but I did not check the database to see if it's public.data or not:

  1. create a .txt file (or other binary file) in Finder
  2. drag the file from Finder to Notes
  3. It shows the same kind of generic attachment symbol, but says "text" instead of "data.

Perhaps public.data is for generic data attachments. You could save the object to disk and maybe check the file type, like using file(1).

Filepaths on iTunes backup from Windows lack account information

It is an itunes backup (should be full), here is the query result on Manifest.db

sqlite> SELECT fileID,relativePath FROM Files WHERE relativePath LIKE '%40DF4BF7-B927-4C5D-B491-6497076749FA%';
bd6085165d412ccd822be2ebd99d0105de49173f|Previews/40DF4BF7-B927-4C5D-B491-6497076749FA-1-288x384-0.png
9807ae55b59a499c85d49da30f8ce391e390b370|Previews/40DF4BF7-B927-4C5D-B491-6497076749FA-1-288x384-0-oriented.png
6f9f363abaf7171f81b7d8f658644c2aae487fb4|Previews/40DF4BF7-B927-4C5D-B491-6497076749FA-1-144x192-0.png
de82a993755cd24e65a4633f62508364e6070819|tmp/HardLinkURLTemp/40DF4BF7-B927-4C5D-B491-6497076749FA
5abcbffbc86fed35eb9dd96c3336fc168d4764c8|tmp/HardLinkURLTemp/40DF4BF7-B927-4C5D-B491-6497076749FA/1593200297
624a906d4f313ab0ce6629fbb135bdd8963bc4ca|tmp/HardLinkURLTemp/40DF4BF7-B927-4C5D-B491-6497076749FA/1593200297/Electrical Hazards.JPG

Originally posted by @devistest in #23 (comment)

tables styles are missing

I have a table in Apple Notes and I made top row bold.

However, it wasn't applied in exported html.

Permission denied @ rb_file_s_rename

Hello!
I did everything according to the instructions for windows (10), and get this error:

PS D:\apple_cloud_notes_parser-master> rake

D:/Ruby26-x64/bin/ruby.exe notes_cloud_ripper.rb --file NoteStore.sqlite

Starting Apple Notes Parser at Sat Feb  1 18:47:55 2020
Storing the results in ./output/2020_02_01-18_47_55

Created a new AppleBackup from single file: NoteStore.sqlite
Traceback (most recent call last):
        8: from notes_cloud_ripper.rb:83:in `<main>'
        7: from notes_cloud_ripper.rb:83:in `new'
        6: from D:/apple_cloud_notes_parser-master/lib/AppleBackup.rb:86:in `initialize'
        5: from D:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/fileutils-1.4.1/lib/fileutils.rb:539:in `mv'
        4: from D:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/fileutils-1.4.1/lib/fileutils.rb:1586:in `fu_each_src_dest'
        3: from D:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/fileutils-1.4.1/lib/fileutils.rb:1604:in `fu_each_src_dest0'
        2: from D:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/fileutils-1.4.1/lib/fileutils.rb:1588:in `block in fu_each_src_dest'
        1: from D:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/fileutils-1.4.1/lib/fileutils.rb:548:in `block in mv'
D:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/fileutils-1.4.1/lib/fileutils.rb:548:in `rename': Permission denied @ rb_file_s_rename - (./output/2020_02_01-18_47_55/test.sqlite, ./output/2020_02_01-18_47_55/NoteStore.sqlite) (Errno::EACCES)
rake aborted!
Command failed with status (1): [D:/Ruby26-x64/bin/ruby.exe notes_cloud_rip...]
D:/apple_cloud_notes_parser-master/Rakefile:7:in `block in <top (required)>'
Tasks: TOP => default => run
(See full trace by running task with --trace)

Mentions

iOS 15 added mentions of other users to Notes. They behave like embedded objects. Need to support them.

database disk image is malformed (SQLite3::CorruptException)

Starting Apple Notes Parser at Mon Dec 21 15:08:39 2020
Storing the results in /Users/dmd/Dropbox/bk/AppleNotes/2020_12_21-15_08_39

Created a new AppleBackup from Mac backup: /Users/dmd/Library/Group Containers/group.com.apple.notes/
Guessed Notes Version: 14
Skipping Note ID 19 due to a missing folder or account, check the debug log for more details.
Skipping Note ID 25 due to a missing folder or account, check the debug log for more details.
Updated AppleNoteStore object with 109 AppleNotes in 8 folders belonging to 1 accounts.
Adding the ZICNOTEDATA.ZPLAINTEXT and ZICNOTEDATA.ZDECOMPRESSEDDATA columns, this takes a few seconds
Traceback (most recent call last):
	13: from notes_cloud_ripper.rb:125:in `<main>'
	12: from notes_cloud_ripper.rb:125:in `each'
	11: from notes_cloud_ripper.rb:127:in `block in <main>'
	10: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:217:in `add_plain_text_to_database'
	 9: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:217:in `each'
	 8: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:220:in `block in add_plain_text_to_database'
	 7: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:137:in `execute'
	 6: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:95:in `prepare'
	 5: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:152:in `block in execute'
	 4: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:152:in `map'
	 3: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `each'
	 2: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `loop'
	 1: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:108:in `block in each'
/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:108:in `step': database disk image is malformed (SQLite3::CorruptException)

CipherError

I'm getting an error while parsing the notes from my backup. The password is correct in the file, and all unencrypted notes can be displayed (tho any with images do not). The error for the cipher is:

Apple Decrypter: Apple Note: 251 Attempting decryption.
Apple Decrypter: Apple Note: 251 caught a CipherError while trying final decrypt, likely the unwrapped key is not correct.

Could be user error, but I'm not sure what I'm doing incorrectly.

com.apple.m4a-audio is unrecognized ZTYPEUTI

OS: Ubuntu 18.04.1 LTS

Starting Apple Notes Parser at Fri Jun  3 15:44:02 2022
Storing the results in ./output/2022_06_03-15_44_02

Created a new AppleBackup from single file: /home/admin/src/NoteStore.sqlite
Guessed Notes Version: 15
com.apple.m4a-audio is unrecognized ZTYPEUTI, please submit a bug report to this project's GitHub repo to report this: https://github.com/threeplanetssoftware/apple_cloud_notes_parser/issues
Skipping Note ID 279 due to a missing folder or account, check the debug log for more details.
Skipping Note ID 542 due to a missing folder or account, check the debug log for more details.
Traceback (most recent call last):
	21: from notes_cloud_ripper.rb:128:in `<main>'
	20: from /home/admin/src/apple_cloud_notes_parser/lib/AppleBackup.rb:157:in `rip_notes'
	19: from /home/admin/src/apple_cloud_notes_parser/lib/AppleBackup.rb:157:in `each'
	18: from /home/admin/src/apple_cloud_notes_parser/lib/AppleBackup.rb:159:in `block in rip_notes'
	17: from /home/admin/src/apple_cloud_notes_parser/lib/AppleNoteStore.rb:193:in `rip_all_objects'
	16: from /home/admin/src/apple_cloud_notes_parser/lib/AppleNoteStore.rb:506:in `rip_notes'
	15: from /var/lib/gems/2.5.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
	14: from /var/lib/gems/2.5.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:151:in `prepare'
	13: from /var/lib/gems/2.5.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:198:in `block in execute'
	12: from /var/lib/gems/2.5.0/gems/sqlite3-1.4.2/lib/sqlite3/resultset.rb:134:in `each'
	11: from /var/lib/gems/2.5.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:199:in `block (2 levels) in execute'
	10: from /home/admin/src/apple_cloud_notes_parser/lib/AppleNoteStore.rb:507:in `block in rip_notes'
	 9: from /home/admin/src/apple_cloud_notes_parser/lib/AppleNoteStore.rb:605:in `rip_note'
	 8: from /var/lib/gems/2.5.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
	 7: from /var/lib/gems/2.5.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:151:in `prepare'
	 6: from /var/lib/gems/2.5.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:198:in `block in execute'
	 5: from /var/lib/gems/2.5.0/gems/sqlite3-1.4.2/lib/sqlite3/resultset.rb:134:in `each'
	 4: from /var/lib/gems/2.5.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:199:in `block (2 levels) in execute'
	 3: from /home/admin/src/apple_cloud_notes_parser/lib/AppleNoteStore.rb:631:in `block in rip_note'
	 2: from /home/admin/src/apple_cloud_notes_parser/lib/AppleCloudKitRecord.rb:31:in `add_cloudkit_sharing_data'
	 1: from /home/admin/src/apple_cloud_notes_parser/lib/AppleCloudKitRecord.rb:31:in `each'
/home/admin/src/apple_cloud_notes_parser/lib/AppleCloudKitRecord.rb:36:in `block in add_cloudkit_sharing_data': undefined method `[]' for nil:NilClass (NoMethodError)

no such column: ZICCLOUDSYNCINGOBJECT.ZMERGEABLEDATA1 (SQLite3::SQLException)

iOS Version:

Adams-MacBook-Pro:apple_cloud_notes_parser lowrya$ sw_vers -productVersion
10.13.6

Stacktrace:

Adams-MacBook-Pro:apple_cloud_notes_parser lowrya$ ruby notes_cloud_ripper.rb -f NoteStore.sqlite

Starting Apple Notes Parser at Sat Feb  1 23:20:05 2020
Storing the results in ./output/2020_02_01-23_20_05

Created a new AppleBackup from single file: NoteStore.sqlite
Guessed Notes Version: 12
public.tiff is unrecognized, please submit a bug report to this project's GitHub repo to report this: https://github.com/threeplanetssoftware/apple_cloud_notes_parser/issues
/Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:147:in `initialize': no such column: ZICCLOUDSYNCINGOBJECT.ZMERGEABLEDATA1 (SQLite3::SQLException)
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:147:in `new'
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:147:in `prepare'
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
	from /Users/lowrya/Programming/apple_cloud_notes_parser/lib/AppleNotesEmbeddedTable.rb:182:in `rebuild_table'
	from /Users/lowrya/Programming/apple_cloud_notes_parser/lib/AppleNotesEmbeddedTable.rb:44:in `initialize'
	from /Users/lowrya/Programming/apple_cloud_notes_parser/lib/AppleNote.rb:161:in `new'
	from /Users/lowrya/Programming/apple_cloud_notes_parser/lib/AppleNote.rb:161:in `block (2 levels) in replace_embedded_objects'
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:199:in `block (2 levels) in execute'
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/resultset.rb:134:in `each'
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:198:in `block in execute'
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:151:in `prepare'
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
	from /Users/lowrya/Programming/apple_cloud_notes_parser/lib/AppleNote.rb:123:in `block in replace_embedded_objects'
	from /Users/lowrya/Programming/apple_cloud_notes_parser/lib/AppleNote.rb:119:in `each'
	from /Users/lowrya/Programming/apple_cloud_notes_parser/lib/AppleNote.rb:119:in `replace_embedded_objects'
	from /Users/lowrya/Programming/apple_cloud_notes_parser/lib/AppleNote.rb:95:in `initialize'
	from /Users/lowrya/Programming/apple_cloud_notes_parser/lib/AppleNoteStore.rb:474:in `new'
	from /Users/lowrya/Programming/apple_cloud_notes_parser/lib/AppleNoteStore.rb:474:in `block in rip_note'
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:199:in `block (2 levels) in execute'
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/resultset.rb:134:in `each'
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:198:in `block in execute'
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:151:in `prepare'
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
	from /Users/lowrya/Programming/apple_cloud_notes_parser/lib/AppleNoteStore.rb:470:in `rip_note'
	from /Users/lowrya/Programming/apple_cloud_notes_parser/lib/AppleNoteStore.rb:404:in `block in rip_notes'
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:199:in `block (2 levels) in execute'
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/resultset.rb:134:in `each'
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:198:in `block in execute'
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:151:in `prepare'
	from /Library/Ruby/Gems/2.3.0/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
	from /Users/lowrya/Programming/apple_cloud_notes_parser/lib/AppleNoteStore.rb:403:in `rip_notes'
	from /Users/lowrya/Programming/apple_cloud_notes_parser/lib/AppleNoteStore.rb:172:in `rip_all_objects'
	from /Users/lowrya/Programming/apple_cloud_notes_parser/lib/AppleBackup.rb:221:in `block in rip_notes'
	from /Users/lowrya/Programming/apple_cloud_notes_parser/lib/AppleBackup.rb:220:in `each'
	from /Users/lowrya/Programming/apple_cloud_notes_parser/lib/AppleBackup.rb:220:in `rip_notes'
	from notes_cloud_ripper.rb:89:in `<main>'

sqlite Table Info:

sqlite> SELECT name,sql FROM sqlite_master WHERE type="table"
   ...> ;
ZICCLOUDSTATE|CREATE TABLE ZICCLOUDSTATE ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZCURRENTLOCALVERSION INTEGER, ZINCLOUD INTEGER, ZLATESTVERSIONSYNCEDTOCLOUD INTEGER, ZCLOUDSYNCINGOBJECT INTEGER, Z2_CLOUDSYNCINGOBJECT INTEGER, ZLOCALVERSIONDATE TIMESTAMP )
ZICCLOUDSYNCINGOBJECT|CREATE TABLE ZICCLOUDSYNCINGOBJECT ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZCRYPTOITERATIONCOUNT INTEGER, ZISPASSWORDPROTECTED INTEGER, ZMARKEDFORDELETION INTEGER, ZMINIMUMSUPPORTEDNOTESVERSION INTEGER, ZNEEDSINITIALFETCHFROMCLOUD INTEGER, ZNEEDSTOBEFETCHEDFROMCLOUD INTEGER, ZNEEDSTOSAVEUSERSPECIFICRECORD INTEGER, ZCLOUDSTATE INTEGER, ZCHECKEDFORLOCATION INTEGER, ZFILESIZE INTEGER, ZHASMARKUPDATA INTEGER, ZIMAGEFILTERTYPE INTEGER, ZORIENTATION INTEGER, ZSECTION INTEGER, ZLOCATION INTEGER, ZMEDIA INTEGER, ZNOTE INTEGER, ZNOTEUSINGTITLEFORNOTETITLE INTEGER, ZPARENTATTACHMENT INTEGER, ZSCALEWHENDRAWING INTEGER, ZVERSION INTEGER, ZVERSIONOUTOFDATE INTEGER, ZATTACHMENT INTEGER, ZSTATE INTEGER, ZACCOUNT INTEGER, ZTYPE INTEGER, ZACCOUNT1 INTEGER, ZATTACHMENT1 INTEGER, ZATTACHMENTVIEWTYPE INTEGER, ZISPINNED INTEGER, ZLEGACYNOTEWASPLAINTEXT INTEGER, ZNOTEHASCHANGES INTEGER, ZPAPERSTYLETYPE INTEGER, ZACCOUNT2 INTEGER, ZFOLDER INTEGER, ZNOTEDATA INTEGER, ZTITLESOURCEATTACHMENT INTEGER, ZISHIDDENNOTECONTAINER INTEGER, ZSORTORDER INTEGER, ZOWNER INTEGER, ZACCOUNTTYPE INTEGER, ZDIDCHOOSETOMIGRATE INTEGER, ZDIDFINISHMIGRATION INTEGER, ZDIDMIGRATEONMAC INTEGER, ZFOLDERTYPE INTEGER, ZIMPORTEDFROMLEGACY INTEGER, ZACCOUNT3 INTEGER, ZPARENT INTEGER, ZCREATIONDATE TIMESTAMP, ZCROPPINGQUADBOTTOMLEFTX FLOAT, ZCROPPINGQUADBOTTOMLEFTY FLOAT, ZCROPPINGQUADBOTTOMRIGHTX FLOAT, ZCROPPINGQUADBOTTOMRIGHTY FLOAT, ZCROPPINGQUADTOPLEFTX FLOAT, ZCROPPINGQUADTOPLEFTY FLOAT, ZCROPPINGQUADTOPRIGHTX FLOAT, ZCROPPINGQUADTOPRIGHTY FLOAT, ZDURATION FLOAT, ZMODIFICATIONDATE TIMESTAMP, ZORIGINX FLOAT, ZORIGINY FLOAT, ZPREVIEWUPDATEDATE TIMESTAMP, ZSIZEHEIGHT FLOAT, ZSIZEWIDTH FLOAT, ZHEIGHT FLOAT, ZMODIFIEDDATE TIMESTAMP, ZSCALE FLOAT, ZWIDTH FLOAT, ZSTATEMODIFICATIONDATE TIMESTAMP, ZMODIFICATIONDATEATIMPORT TIMESTAMP, ZCREATIONDATE1 TIMESTAMP, ZFOLDERMODIFICATIONDATE TIMESTAMP, ZLASTNOTIFIEDDATE TIMESTAMP, ZLASTVIEWEDMODIFICATIONDATE TIMESTAMP, ZLEGACYMODIFICATIONDATEATIMPORT TIMESTAMP, ZMODIFICATIONDATE1 TIMESTAMP, ZDATEFORLASTTITLEMODIFICATION TIMESTAMP, ZPARENTMODIFICATIONDATE TIMESTAMP, ZIDENTIFIER VARCHAR UNIQUE, ZPASSWORDHINT VARCHAR, ZZONEOWNERNAME VARCHAR, ZADDITIONALINDEXABLETEXT VARCHAR, ZFALLBACKSUBTITLEIOS VARCHAR, ZFALLBACKSUBTITLEMAC VARCHAR, ZFALLBACKTITLE VARCHAR, ZREMOTEFILEURLSTRING VARCHAR, ZSUMMARY VARCHAR, ZTITLE VARCHAR, ZTYPEUTI VARCHAR, ZURLSTRING VARCHAR, ZUSERTITLE VARCHAR, ZDEVICEIDENTIFIER VARCHAR, ZCONTENTHASHATIMPORT VARCHAR, ZFILENAME VARCHAR, ZLEGACYCONTENTHASHATIMPORT VARCHAR, ZLEGACYIMPORTDEVICEIDENTIFIER VARCHAR, ZLEGACYMANAGEDOBJECTIDURIREPRESENTATION VARCHAR, ZSELECTEDINKCOLORSTRING VARCHAR, ZSELECTEDINKIDENTIFIER VARCHAR, ZSNIPPET VARCHAR, ZTHUMBNAILATTACHMENTIDENTIFIER VARCHAR, ZTITLE1 VARCHAR, ZACCOUNTNAMEFORACCOUNTLISTSORTING VARCHAR, ZNESTEDTITLEFORSORTING VARCHAR, ZNAME VARCHAR, ZUSERRECORDNAME VARCHAR, ZTITLE2 VARCHAR, ZASSETCRYPTOINITIALIZATIONVECTOR BLOB, ZASSETCRYPTOTAG BLOB, ZCRYPTOINITIALIZATIONVECTOR BLOB, ZCRYPTOSALT BLOB, ZCRYPTOTAG BLOB, ZCRYPTOWRAPPEDKEY BLOB, ZENCRYPTEDVALUESJSON BLOB, ZSERVERRECORDDATA BLOB, ZSERVERSHAREDATA BLOB, ZUNAPPLIEDENCRYPTEDRECORD BLOB, ZUSERSPECIFICSERVERRECORDDATA BLOB, ZFALLBACKIMAGECRYPTOINITIALIZATIONVECTOR BLOB, ZFALLBACKIMAGECRYPTOTAG BLOB, ZMARKUPMODELDATA BLOB, ZMERGEABLEDATA BLOB, ZMETADATADATA BLOB, ZCRYPTOMETADATAINITIALIZATIONVECTOR BLOB, ZCRYPTOMETADATATAG BLOB, ZENCRYPTEDMETADATA BLOB, ZMETADATA BLOB, ZLASTNOTIFIEDTIMESTAMPDATA BLOB, ZLASTVIEWEDTIMESTAMPDATA BLOB, ZREPLICAIDTOUSERIDDICTDATA BLOB, ZCRYPTOVERIFIER BLOB )
ZICLOCATION|CREATE TABLE ZICLOCATION ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZPLACEUPDATED INTEGER, ZATTACHMENT INTEGER, ZLATITUDE FLOAT, ZLONGITUDE FLOAT, ZPLACEMARKDATA BLOB )
ZICNOTEDATA|CREATE TABLE ZICNOTEDATA ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZNOTE INTEGER, ZCRYPTOINITIALIZATIONVECTOR BLOB, ZCRYPTOTAG BLOB, ZDATA BLOB )
ZICSEARCHINDEXTRANSACTION|CREATE TABLE ZICSEARCHINDEXTRANSACTION ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZLASTTRANSACTIONID INTEGER, ZIDENTIFIER VARCHAR )
ZICSERVERCHANGETOKEN|CREATE TABLE ZICSERVERCHANGETOKEN ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZDATABASESCOPE INTEGER, ZACCOUNT INTEGER, ZOWNERNAME VARCHAR, ZZONENAME VARCHAR, ZCKSERVERCHANGETOKENDATA BLOB )
ZNEXTID|CREATE TABLE ZNEXTID ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZCOUNTER INTEGER )
Z_PRIMARYKEY|CREATE TABLE Z_PRIMARYKEY (Z_ENT INTEGER PRIMARY KEY, Z_NAME VARCHAR, Z_SUPER INTEGER, Z_MAX INTEGER)
Z_METADATA|CREATE TABLE Z_METADATA (Z_VERSION INTEGER PRIMARY KEY, Z_UUID VARCHAR(255), Z_PLIST BLOB)
Z_MODELCACHE|CREATE TABLE Z_MODELCACHE (Z_CONTENT BLOB)
ACHANGE|CREATE TABLE ACHANGE ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZCHANGETYPE INTEGER, ZENTITY INTEGER, ZENTITYPK INTEGER, ZTRANSACTIONID INTEGER, ZCOLUMNS BLOB )
ATRANSACTION|CREATE TABLE ATRANSACTION ( Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZTIMESTAMP FLOAT, ZAUTHOR VARCHAR, ZBUNDLEID VARCHAR, ZCONTEXTNAME VARCHAR, ZPROCESSID VARCHAR, ZQUERYGEN BLOB )

Table exists, column doesn't. Here's the column info for ZICCLOUDSYNCINGOBJECT

sqlite> pragma table_info(ZICCLOUDSYNCINGOBJECT);
0|Z_PK|INTEGER|0||1
1|Z_ENT|INTEGER|0||0
2|Z_OPT|INTEGER|0||0
3|ZCRYPTOITERATIONCOUNT|INTEGER|0||0
4|ZISPASSWORDPROTECTED|INTEGER|0||0
5|ZMARKEDFORDELETION|INTEGER|0||0
6|ZMINIMUMSUPPORTEDNOTESVERSION|INTEGER|0||0
7|ZNEEDSINITIALFETCHFROMCLOUD|INTEGER|0||0
8|ZNEEDSTOBEFETCHEDFROMCLOUD|INTEGER|0||0
9|ZNEEDSTOSAVEUSERSPECIFICRECORD|INTEGER|0||0
10|ZCLOUDSTATE|INTEGER|0||0
11|ZCHECKEDFORLOCATION|INTEGER|0||0
12|ZFILESIZE|INTEGER|0||0
13|ZHASMARKUPDATA|INTEGER|0||0
14|ZIMAGEFILTERTYPE|INTEGER|0||0
15|ZORIENTATION|INTEGER|0||0
16|ZSECTION|INTEGER|0||0
17|ZLOCATION|INTEGER|0||0
18|ZMEDIA|INTEGER|0||0
19|ZNOTE|INTEGER|0||0
20|ZNOTEUSINGTITLEFORNOTETITLE|INTEGER|0||0
21|ZPARENTATTACHMENT|INTEGER|0||0
22|ZSCALEWHENDRAWING|INTEGER|0||0
23|ZVERSION|INTEGER|0||0
24|ZVERSIONOUTOFDATE|INTEGER|0||0
25|ZATTACHMENT|INTEGER|0||0
26|ZSTATE|INTEGER|0||0
27|ZACCOUNT|INTEGER|0||0
28|ZTYPE|INTEGER|0||0
29|ZACCOUNT1|INTEGER|0||0
30|ZATTACHMENT1|INTEGER|0||0
31|ZATTACHMENTVIEWTYPE|INTEGER|0||0
32|ZISPINNED|INTEGER|0||0
33|ZLEGACYNOTEWASPLAINTEXT|INTEGER|0||0
34|ZNOTEHASCHANGES|INTEGER|0||0
35|ZPAPERSTYLETYPE|INTEGER|0||0
36|ZACCOUNT2|INTEGER|0||0
37|ZFOLDER|INTEGER|0||0
38|ZNOTEDATA|INTEGER|0||0
39|ZTITLESOURCEATTACHMENT|INTEGER|0||0
40|ZISHIDDENNOTECONTAINER|INTEGER|0||0
41|ZSORTORDER|INTEGER|0||0
42|ZOWNER|INTEGER|0||0
43|ZACCOUNTTYPE|INTEGER|0||0
44|ZDIDCHOOSETOMIGRATE|INTEGER|0||0
45|ZDIDFINISHMIGRATION|INTEGER|0||0
46|ZDIDMIGRATEONMAC|INTEGER|0||0
47|ZFOLDERTYPE|INTEGER|0||0
48|ZIMPORTEDFROMLEGACY|INTEGER|0||0
49|ZACCOUNT3|INTEGER|0||0
50|ZPARENT|INTEGER|0||0
51|ZCREATIONDATE|TIMESTAMP|0||0
52|ZCROPPINGQUADBOTTOMLEFTX|FLOAT|0||0
53|ZCROPPINGQUADBOTTOMLEFTY|FLOAT|0||0
54|ZCROPPINGQUADBOTTOMRIGHTX|FLOAT|0||0
55|ZCROPPINGQUADBOTTOMRIGHTY|FLOAT|0||0
56|ZCROPPINGQUADTOPLEFTX|FLOAT|0||0
57|ZCROPPINGQUADTOPLEFTY|FLOAT|0||0
58|ZCROPPINGQUADTOPRIGHTX|FLOAT|0||0
59|ZCROPPINGQUADTOPRIGHTY|FLOAT|0||0
60|ZDURATION|FLOAT|0||0
61|ZMODIFICATIONDATE|TIMESTAMP|0||0
62|ZORIGINX|FLOAT|0||0
63|ZORIGINY|FLOAT|0||0
64|ZPREVIEWUPDATEDATE|TIMESTAMP|0||0
65|ZSIZEHEIGHT|FLOAT|0||0
66|ZSIZEWIDTH|FLOAT|0||0
67|ZHEIGHT|FLOAT|0||0
68|ZMODIFIEDDATE|TIMESTAMP|0||0
69|ZSCALE|FLOAT|0||0
70|ZWIDTH|FLOAT|0||0
71|ZSTATEMODIFICATIONDATE|TIMESTAMP|0||0
72|ZMODIFICATIONDATEATIMPORT|TIMESTAMP|0||0
73|ZCREATIONDATE1|TIMESTAMP|0||0
74|ZFOLDERMODIFICATIONDATE|TIMESTAMP|0||0
75|ZLASTNOTIFIEDDATE|TIMESTAMP|0||0
76|ZLASTVIEWEDMODIFICATIONDATE|TIMESTAMP|0||0
77|ZLEGACYMODIFICATIONDATEATIMPORT|TIMESTAMP|0||0
78|ZMODIFICATIONDATE1|TIMESTAMP|0||0
79|ZDATEFORLASTTITLEMODIFICATION|TIMESTAMP|0||0
80|ZPARENTMODIFICATIONDATE|TIMESTAMP|0||0
81|ZIDENTIFIER|VARCHAR|0||0
82|ZPASSWORDHINT|VARCHAR|0||0
83|ZZONEOWNERNAME|VARCHAR|0||0
84|ZADDITIONALINDEXABLETEXT|VARCHAR|0||0
85|ZFALLBACKSUBTITLEIOS|VARCHAR|0||0
86|ZFALLBACKSUBTITLEMAC|VARCHAR|0||0
87|ZFALLBACKTITLE|VARCHAR|0||0
88|ZREMOTEFILEURLSTRING|VARCHAR|0||0
89|ZSUMMARY|VARCHAR|0||0
90|ZTITLE|VARCHAR|0||0
91|ZTYPEUTI|VARCHAR|0||0
92|ZURLSTRING|VARCHAR|0||0
93|ZUSERTITLE|VARCHAR|0||0
94|ZDEVICEIDENTIFIER|VARCHAR|0||0
95|ZCONTENTHASHATIMPORT|VARCHAR|0||0
96|ZFILENAME|VARCHAR|0||0
97|ZLEGACYCONTENTHASHATIMPORT|VARCHAR|0||0
98|ZLEGACYIMPORTDEVICEIDENTIFIER|VARCHAR|0||0
99|ZLEGACYMANAGEDOBJECTIDURIREPRESENTATION|VARCHAR|0||0
100|ZSELECTEDINKCOLORSTRING|VARCHAR|0||0
101|ZSELECTEDINKIDENTIFIER|VARCHAR|0||0
102|ZSNIPPET|VARCHAR|0||0
103|ZTHUMBNAILATTACHMENTIDENTIFIER|VARCHAR|0||0
104|ZTITLE1|VARCHAR|0||0
105|ZACCOUNTNAMEFORACCOUNTLISTSORTING|VARCHAR|0||0
106|ZNESTEDTITLEFORSORTING|VARCHAR|0||0
107|ZNAME|VARCHAR|0||0
108|ZUSERRECORDNAME|VARCHAR|0||0
109|ZTITLE2|VARCHAR|0||0
110|ZASSETCRYPTOINITIALIZATIONVECTOR|BLOB|0||0
111|ZASSETCRYPTOTAG|BLOB|0||0
112|ZCRYPTOINITIALIZATIONVECTOR|BLOB|0||0
113|ZCRYPTOSALT|BLOB|0||0
114|ZCRYPTOTAG|BLOB|0||0
115|ZCRYPTOWRAPPEDKEY|BLOB|0||0
116|ZENCRYPTEDVALUESJSON|BLOB|0||0
117|ZSERVERRECORDDATA|BLOB|0||0
118|ZSERVERSHAREDATA|BLOB|0||0
119|ZUNAPPLIEDENCRYPTEDRECORD|BLOB|0||0
120|ZUSERSPECIFICSERVERRECORDDATA|BLOB|0||0
121|ZFALLBACKIMAGECRYPTOINITIALIZATIONVECTOR|BLOB|0||0
122|ZFALLBACKIMAGECRYPTOTAG|BLOB|0||0
123|ZMARKUPMODELDATA|BLOB|0||0
124|ZMERGEABLEDATA|BLOB|0||0
125|ZMETADATADATA|BLOB|0||0
126|ZCRYPTOMETADATAINITIALIZATIONVECTOR|BLOB|0||0
127|ZCRYPTOMETADATATAG|BLOB|0||0
128|ZENCRYPTEDMETADATA|BLOB|0||0
129|ZMETADATA|BLOB|0||0
130|ZLASTNOTIFIEDTIMESTAMPDATA|BLOB|0||0
131|ZLASTVIEWEDTIMESTAMPDATA|BLOB|0||0
132|ZREPLICAIDTOUSERIDDICTDATA|BLOB|0||0
133|ZCRYPTOVERIFIER|BLOB|0||0

Two more features missing

I think if you add checklist element and also native link they should be saved into inline embedded objects.

Similar to tags and mentions. See screenshot how to create those elements.

Screen Shot 2022-09-07 at 12 43 10 PM

Basically this information is lost for now.

Extracted Note Body is Truncated/Incomplete

First of all, great work on figuring out the notes format in the first place.

I'm in the process of converting your implementation to Swift, and I stumbled across what I believe to be a flaw in the original code. The extracted plaintext appears to be erroneously truncated in both the intermediate file and in the ZDECOMPRESSEDTEXT column.

I believe the problem is introduced in the get_plaintext function in the lines:
# Read the next byte as the length of plain text
$string_length = ord substr($input_string, $pointer, 1);

A single byte would limit the potential note length to 255 characters, would it not?
I've never worked with Perl before, so this could be a misinterpretation of what's going on here.
I don't know the proper number of bytes to read for the length field, or I would submit a pull request, but I figured that I should at least present the problem.

line breaks and indentation not preserved in HTML output

The HTML output viewed in a browser doesn't show line breaks and indentation correctly.

The source shows multiple lines without
, but HTML doesn't preserve those line breaks.
Similarly for multiple whitespaces for indentation.

I added this CSS and the formatting looks more correct.

lawm@1876929

But it's not perfect. It adds more line breaks in the note index at the top.

HTML export issue

I have some notes that are breaking up sentences and words into multiple bullet points.

Example in Notes:

  • List:
    • Benefits describe...

Turns into:

  • Benefit
  • s de
  • sc
  • ribe

Screenshot:
screenshot

Not quite sure what the pattern is, as there doesn't seem to be anything odd in the Note.

Decrypt with unknown password

Hi is there a way to decrypt the notes without knowing the password? I forgot my password and need the locked notes.

undefined method `primary_key' for nil:NilClass (NoMethodError)

$ rake --trace
** Invoke default (first_time)
** Invoke run (first_time)
** Execute run
/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby notes_cloud_ripper.rb --file NoteStore.sqlite

Starting Apple Notes Parser at Sun Jul 19 12:32:42 2020
Storing the results in ./output/2020_07_19-12_32_42

Created a new AppleBackup from single file: NoteStore.sqlite
Guessed Notes Version: 13
Updated AppleNoteStore object with 102 AppleNotes in 8 folders belonging to 1 accounts.
Adding the ZICNOTEDATA.ZPLAINTEXT and ZICNOTEDATA.ZDECOMPRESSEDDATA columns, this takes a few seconds
Traceback (most recent call last):
	8: from notes_cloud_ripper.rb:123:in `<main>'
	7: from notes_cloud_ripper.rb:123:in `each'
	6: from notes_cloud_ripper.rb:126:in `block in <main>'
	5: from notes_cloud_ripper.rb:126:in `open'
	4: from notes_cloud_ripper.rb:127:in `block (2 levels) in <main>'
	3: from /Users/dmd/apple_cloud_notes_parser/lib/AppleNoteStore.rb:530:in `generate_html'
	2: from /Users/dmd/apple_cloud_notes_parser/lib/AppleNoteStore.rb:530:in `each'
	1: from /Users/dmd/apple_cloud_notes_parser/lib/AppleNoteStore.rb:532:in `block in generate_html'
/Users/dmd/apple_cloud_notes_parser/lib/AppleNote.rb:354:in `generate_html': undefined method `primary_key' for nil:NilClass (NoMethodError)
rake aborted!
Command failed with status (1): [/System/Library/Frameworks/Ruby.framework/...]
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/file_utils.rb:67:in `block in create_shell_runner'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/file_utils.rb:57:in `sh'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/file_utils.rb:105:in `ruby'
/Users/dmd/apple_cloud_notes_parser/Rakefile:7:in `block in <top (required)>'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/task.rb:273:in `block in execute'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/task.rb:273:in `each'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/task.rb:273:in `execute'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/task.rb:214:in `block in invoke_with_call_chain'
/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/monitor.rb:230:in `mon_synchronize'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/task.rb:194:in `invoke_with_call_chain'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/task.rb:238:in `block in invoke_prerequisites'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/task.rb:236:in `each'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/task.rb:236:in `invoke_prerequisites'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/task.rb:213:in `block in invoke_with_call_chain'
/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/monitor.rb:230:in `mon_synchronize'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/task.rb:194:in `invoke_with_call_chain'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/task.rb:183:in `invoke'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/application.rb:160:in `invoke_task'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/application.rb:116:in `each'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/application.rb:116:in `block in top_level'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/application.rb:125:in `run_with_threads'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/application.rb:110:in `top_level'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/application.rb:83:in `block in run'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/application.rb:186:in `standard_exception_handling'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/lib/rake/application.rb:80:in `run'
/Library/Ruby/Gems/2.6.0/gems/rake-12.3.2/exe/rake:27:in `<top (required)>'
/usr/bin/rake:23:in `load'
/usr/bin/rake:23:in `<main>'
Tasks: TOP => default => run

Deleted Note shows up in CSV

I think deleted note shows up in CSV file. Tried few times and it is still there.
Is it possible to not have those? Or is it possible to have some extra column marking notes as deleted.

`nil` error during HTML generation

(Follow-up to unrelated #40)

I'm getting a crash on one of my notes during HTML generation:

Created a new AppleBackup from Mac backup: /Users/huyz/Library/Group Containers/group.com.apple.notes
Guessed Notes Version: 15
Apple Decrypter: Attempting to decrypt objects without a password list set, check the -w option for more success
Updated AppleNoteStore object with 167 AppleNotes in 19 folders belonging to 1 accounts.
Adding the ZICNOTEDATA.ZPLAINTEXT and ZICNOTEDATA.ZDECOMPRESSEDDATA columns, this takes a few seconds
/Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:589:in `+': no implicit conversion of nil into String (TypeError)
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:589:in `block in generate_html_text'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:562:in `each'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:562:in `each_with_index'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:562:in `generate_html_text'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:527:in `generate_html'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNoteStore.rb:742:in `block in generate_html'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNoteStore.rb:740:in `each'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNoteStore.rb:740:in `generate_html'
	from notes_cloud_ripper.rb:178:in `block (2 levels) in <main>'
	from notes_cloud_ripper.rb:177:in `open'
	from notes_cloud_ripper.rb:177:in `block in <main>'
	from notes_cloud_ripper.rb:171:in `each'
	from notes_cloud_ripper.rb:171:in `<main>'

Here, for the line

          html += @embedded_objects[embedded_object_index].generate_html# + "\n"

embedded_object_index is 0 and @embedded_objects looks like:
screenshot 2022-08-06T035407Z

Strange to have some nils in there.

I'm in the debugger if you want me to check the state at specific lines.

Parser issue

I think currently if you have table and have mention or tag in the table - it will break.

So minor use case - but still wanted to highlight it.

0.8 release fails on block in rip_note': undefined local variable or method `server_share_data'

After latest git pull this morning:

Traceback (most recent call last):
	22: from notes_cloud_ripper.rb:122:in `<main>'
	21: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleBackup.rb:124:in `rip_notes'
	20: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleBackup.rb:124:in `each'
	19: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleBackup.rb:126:in `block in rip_notes'
	18: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:187:in `rip_all_objects'
	17: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:487:in `rip_notes'
	16: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:137:in `execute'
	15: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:95:in `prepare'
	14: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:143:in `block in execute'
	13: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `each'
	12: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `loop'
	11: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:110:in `block in each'
	10: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:145:in `block (2 levels) in execute'
	 9: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:488:in `block in rip_notes'
	 8: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:573:in `rip_note'
	 7: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:137:in `execute'
	 6: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:95:in `prepare'
	 5: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:143:in `block in execute'
	 4: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `each'
	 3: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `loop'
	 2: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:110:in `block in each'
	 1: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:145:in `block (2 levels) in execute'
/Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:599:in `block in rip_note': undefined local variable or method `server_share_data' for #<AppleNoteStore:0x00007f91b8089b60> (NameError)
Did you mean?  server_share_column

com.compuserve.gif is unrecognized

I just got this message:

com.compuserve.gif is unrecognized, please submit a bug report to this project's GitHub repo to report this: https://github.com/threeplanetssoftware/apple_cloud_notes_parser/issues

I am on head of 21-wal-copy (5f1db93d44b60f3c4161046d2830d10da83b20d5). Has that been merged? Can I go back to master?

AppleNote.rb:123:in `decode': Error occurred during parsing: Invalid wire type (Google::Protobuf::ParseError)


Starting Apple Notes Parser at Mon Mar 15 14:31:27 2021
Storing the results in /Users/dmd/Dropbox/bk/AppleNotes/2021_03_15-14_31_27

Created a new AppleBackup from Mac backup: /Users/dmd/Library/Group Containers/group.com.apple.notes/
Guessed Notes Version: 14
Skipping Note ID 19 due to a missing folder or account, check the debug log for more details.
Skipping Note ID 25 due to a missing folder or account, check the debug log for more details.
Traceback (most recent call last):
	26: from notes_cloud_ripper.rb:122:in `<main>'
	25: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleBackup.rb:124:in `rip_notes'
	24: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleBackup.rb:124:in `each'
	23: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleBackup.rb:126:in `block in rip_notes'
	22: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:187:in `rip_all_objects'
	21: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:487:in `rip_notes'
	20: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:137:in `execute'
	19: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:95:in `prepare'
	18: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:143:in `block in execute'
	17: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `each'
	16: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `loop'
	15: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:110:in `block in each'
	14: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:145:in `block (2 levels) in execute'
	13: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:488:in `block in rip_notes'
	12: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:573:in `rip_note'
	11: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:137:in `execute'
	10: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:95:in `prepare'
	 9: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:143:in `block in execute'
	 8: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `each'
	 7: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `loop'
	 6: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:110:in `block in each'
	 5: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:145:in `block (2 levels) in execute'
	 4: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:583:in `block in rip_note'
	 3: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:583:in `new'
	 2: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNote.rb:105:in `initialize'
	 1: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNote.rb:123:in `extract_plaintext'
/Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNote.rb:123:in `decode': Error occurred during parsing: Invalid wire type (Google::Protobuf::ParseError)

Encrypted data not supported

Many of my notes are not decompressed since they are encrypted.
Apple calls this locked, this can either be with a password or touch id.

Working on note 31
                Skipping note 31 as it appears to be encrypted or otherwise not parsed correctly

I got the password for this, but I'm not sure how to decrypt the notes. Can you support this?

AppleNotesEmbeddedTable.rb:142:in `block (2 levels) in parse_cell_columns': undefined method `[]=' for nil:NilClass (NoMethodError)

The tool is failing to parse a table in my notes.
I'm not sure which table and they're my personal notes, so I can't upload it to you.

I enabled the col/row print, but it may not help much.

Versions

* Notes db from macOS 10.14.6
* apple_cloud_notes_parser$ git log --oneline -1
b1fdb8b (HEAD -> master, tag: v0.6-beta, origin/master, origin/HEAD) Updated README to account for new Mac option.

Log

$ ruby notes_cloud_ripper.rb -m ../group.com.apple.notes

Starting Apple Notes Parser at Sun May 17 15:37:25 2020
Storing the results in ./output/2020_05_17-15_37_25

Created a new AppleBackup from Mac backup: ../group.com.apple.notes
Guessed Notes Version: 12
Current row: 3, Current column: 5
Total rows: 2, Total columns: 3
1, 0
Current row: 1, Current column: 5
Total rows: 2, Total columns: 3
0, 0
Current row: 3, Current column: 7
Total rows: 2, Total columns: 3
1, 1
Current row: 1, Current column: 7
Total rows: 2, Total columns: 3
0, 1
Current row: 3, Current column: 9
Total rows: 2, Total columns: 3
1, 2
Current row: 1, Current column: 9
Total rows: 2, Total columns: 3
0, 2
Current row: 1, Current column: 4
Total rows: 3, Total columns: 5
0, 4
Traceback (most recent call last):
        48: from notes_cloud_ripper.rb:103:in `<main>'
        47: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleBackup.rb:100:in `rip_notes'
        46: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleBackup.rb:100:in `each'
        45: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleBackup.rb:101:in `block in rip_notes'
        44: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNoteStore.rb:174:in `rip_all_objects'
        43: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNoteStore.rb:405:in `rip_notes'
        42: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
        41: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:151:in `prepare'
        40: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:198:in `block in execute'
        39: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/resultset.rb:134:in `each'
        38: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:199:in `block (2 levels) in execute'
        37: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNoteStore.rb:406:in `block in rip_notes'
        36: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNoteStore.rb:472:in `rip_note'
        35: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
        34: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:151:in `prepare'
        33: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:198:in `block in execute'
        32: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/resultset.rb:134:in `each'
        31: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:199:in `block (2 levels) in execute'
        30: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNoteStore.rb:476:in `block in rip_note'
        29: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNoteStore.rb:476:in `new'
        28: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNote.rb:97:in `initialize'
        27: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNote.rb:129:in `replace_embedded_objects'
        26: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNote.rb:129:in `each'
        25: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNote.rb:135:in `block in replace_embedded_objects'
        24: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
        23: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:151:in `prepare'
        22: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:198:in `block in execute'
        21: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/resultset.rb:134:in `each'
        20: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:199:in `block (2 levels) in execute'
        19: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNote.rb:173:in `block (2 levels) in replace_embedded_objects'
        18: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNote.rb:173:in `new'
        17: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNotesEmbeddedTable.rb:46:in `initialize'
        16: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNotesEmbeddedTable.rb:203:in `rebuild_table'
        15: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:193:in `execute'
        14: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:151:in `prepare'
        13: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:198:in `block in execute'
        12: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/resultset.rb:134:in `each'
        11: from /home/l/gems/gems/sqlite3-1.4.2/lib/sqlite3/database.rb:199:in `block (2 levels) in execute'
        10: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNotesEmbeddedTable.rb:248:in `block in rebuild_table'
         9: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNotesEmbeddedTable.rb:248:in `each'
         8: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNotesEmbeddedTable.rb:250:in `block (2 levels) in rebuild_table'
         7: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNotesEmbeddedTable.rb:158:in `parse_table'
         6: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNotesEmbeddedTable.rb:158:in `each'
         5: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNotesEmbeddedTable.rb:173:in `block in parse_table'
         4: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNotesEmbeddedTable.rb:131:in `parse_cell_columns'
         3: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNotesEmbeddedTable.rb:131:in `each'
         2: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNotesEmbeddedTable.rb:136:in `block in parse_cell_columns'
         1: from /home/l/notes-test/apple_cloud_notes_parser/lib/AppleNotesEmbeddedTable.rb:136:in `each'
/home/l/notes-test/apple_cloud_notes_parser/lib/AppleNotesEmbeddedTable.rb:142:in `block (2 levels) in parse_cell_columns': undefined method `[]=' for nil:NilClass (NoMethodError)

Can I send a few buck on your way as a sign of appreciation?

Hey there,

This project saved me so much time recovering bunch of notes from a recovery hard disk recently!

As an appreciation I'd like to send your way few bucks, if you're interested, however I am not willing to become a GitHub sponsor (monthly contribution).

Please shoot me an email at [email protected] if you're interested.

Thank you!

checklist html generation bug

I see unclosed tag when I add checklist to the note:

Here is fourth list<br/>
<ul class='checklist'><li class='unchecked'>Apple</li><li class='unchecked'>Watermelon</li><li class='checked'>Orange</div> <!-- Close the 'note-content' div -->

see at the end there is closing div, but no closing li or ul.

undefined method `bytesize'

Traceback (most recent call last):
	29: from notes_cloud_ripper.rb:128:in `<main>'
	28: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleBackup.rb:124:in `rip_notes'
	27: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleBackup.rb:124:in `each'
	26: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleBackup.rb:126:in `block in rip_notes'
	25: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:187:in `rip_all_objects'
	24: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:487:in `rip_notes'
	23: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:137:in `execute'
	22: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:95:in `prepare'
	21: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:143:in `block in execute'
	20: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `each'
	19: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `loop'
	18: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:110:in `block in each'
	17: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:145:in `block (2 levels) in execute'
	16: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:488:in `block in rip_notes'
	15: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:573:in `rip_note'
	14: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:137:in `execute'
	13: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:95:in `prepare'
	12: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:143:in `block in execute'
	11: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `each'
	10: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:107:in `loop'
	 9: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/statement.rb:110:in `block in each'
	 8: from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0/gems/sqlite3-1.3.13/lib/sqlite3/database.rb:145:in `block (2 levels) in execute'
	 7: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleNoteStore.rb:599:in `block in rip_note'
	 6: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleCloudKitRecord.rb:28:in `add_cloudkit_sharing_data'
	 5: from /Users/dmd/Dropbox (Personal)/code/apple_cloud_notes_parser/lib/AppleCloudKitRecord.rb:28:in `new'
	 4: from /Library/Ruby/Gems/2.6.0/gems/keyed_archive-1.0.0/lib/keyed_archive.rb:18:in `initialize'
	 3: from /Library/Ruby/Gems/2.6.0/gems/keyed_archive-1.0.0/lib/keyed_archive.rb:18:in `new'
	 2: from /Library/Ruby/Gems/2.6.0/gems/CFPropertyList-3.0.2/lib/cfpropertylist/rbCFPropertyList.rb:239:in `initialize'
	 1: from /Library/Ruby/Gems/2.6.0/gems/CFPropertyList-3.0.2/lib/cfpropertylist/rbCFPropertyList.rb:321:in `load_str'
/Library/Ruby/Gems/2.6.0/gems/CFPropertyList-3.0.2/lib/cfpropertylist/rbBinaryCFPropertyList.rb:38:in `load': undefined method `bytesize' for nil:NilClass (NoMethodError)

Trying to decrypt with known password: cannot load such file -- keyed_archive (LoadError)

Hi,

I'm trying to parse and decrypt a NoteStore.sqlite file with a known password, that is 100% correct.
I followed the install guide on
However I'm running into some problems. I'm quite new to Ruby / OS X . Any suggestions what exactly is giving me the 'LoadError'?

iMac-van-Derk:apple_cloud_notes_parser-master derk$ rake --trace
** Invoke default (first_time)
** Invoke run (first_time)
** Execute run
/usr/local/Cellar/ruby/3.1.1/bin/ruby notes_cloud_ripper.rb --file NoteStore.sqlite
internal:/usr/local/Cellar/ruby/3.1.1/lib/ruby/3.1.0/rubygems/core_ext/kernel_require.rb:85:in require': cannot load such file -- keyed_archive (LoadError) from <internal:/usr/local/Cellar/ruby/3.1.1/lib/ruby/3.1.0/rubygems/core_ext/kernel_require.rb>:85:in require'
from /Users/derk/apple_cloud_notes_parser-master/lib/AppleNote.rb:1:in <top (required)>' from /Users/derk/apple_cloud_notes_parser-master/lib/AppleBackup.rb:4:in require_relative'
from /Users/derk/apple_cloud_notes_parser-master/lib/AppleBackup.rb:4:in <top (required)>' from notes_cloud_ripper.rb:5:in require_relative'
from notes_cloud_ripper.rb:5:in <main>' rake aborted! Command failed with status (1): [/usr/local/Cellar/ruby/3.1.1/bin/ruby note...] /usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/file_utils.rb:67:in block in create_shell_runner'
/usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/file_utils.rb:57:in sh' /usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/file_utils.rb:104:in ruby'
/Users/derk/apple_cloud_notes_parser-master/Rakefile:7:in block in <top (required)>' /usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:281:in block in execute'
/usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:281:in each' /usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:281:in execute'
/usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:219:in block in invoke_with_call_chain' /usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:199:in synchronize'
/usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:199:in invoke_with_call_chain' /usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:243:in block in invoke_prerequisites'
/usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:241:in each' /usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:241:in invoke_prerequisites'
/usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:218:in block in invoke_with_call_chain' /usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:199:in synchronize'
/usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:199:in invoke_with_call_chain' /usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/task.rb:188:in invoke'
/usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/application.rb:160:in invoke_task' /usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/application.rb:116:in block (2 levels) in top_level'
/usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/application.rb:116:in each' /usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/application.rb:116:in block in top_level'
/usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/application.rb:125:in run_with_threads' /usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/application.rb:110:in top_level'
/usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/application.rb:83:in block in run' /usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/application.rb:186:in standard_exception_handling'
/usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/lib/rake/application.rb:80:in run' /usr/local/Cellar/ruby/3.1.1/lib/ruby/gems/3.1.0/gems/rake-13.0.6/exe/rake:27:in <top (required)>'
/usr/local/opt/ruby/bin/rake:25:in load' /usr/local/opt/ruby/bin/rake:25:in

'
Tasks: TOP => default => run

Crash: `buffer error` in `Zlib::BufError`

Right up around:

D, [2022-09-23T19:56:12.946136 #12992] DEBUG -- : AppleNote: Note 6967 replacing attachment 07BDBD12-9FA6-498B-ABC6-9B1066D51DCB
D, [2022-09-23T19:56:12.946155 #12992] DEBUG -- : Note 6967: Created a new Embedded Object of type com.apple.notes.gallery

the app crashes with:

/Users/huyz/git/apple_cloud_notes_parser/lib/AppleNotesEmbeddedGallery.rb:93:in `inflate': buffer error (Zlib::BufError)
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNotesEmbeddedGallery.rb:93:in `add_gallery_children'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNotesEmbeddedGallery.rb:25:in `initialize'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:261:in `new'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:261:in `block (2 levels) in replace_embedded_objects'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:204:in `block (2 levels) in execute'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/resultset.rb:134:in `each'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:203:in `block in execute'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:156:in `prepare'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:198:in `execute'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:173:in `block in replace_embedded_objects'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:153:in `each'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:153:in `replace_embedded_objects'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNote.rb:114:in `initialize'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNoteStore.rb:615:in `new'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNoteStore.rb:615:in `block in rip_note'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:204:in `block (2 levels) in execute'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/resultset.rb:134:in `each'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:203:in `block in execute'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:156:in `prepare'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:198:in `execute'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNoteStore.rb:605:in `rip_note'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNoteStore.rb:507:in `block in rip_notes'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:204:in `block (2 levels) in execute'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/resultset.rb:134:in `each'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:203:in `block in execute'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:156:in `prepare'
	from /Users/huyz/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/sqlite3-1.4.4/lib/sqlite3/database.rb:198:in `execute'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNoteStore.rb:506:in `rip_notes'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleNoteStore.rb:193:in `rip_all_objects'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleBackup.rb:165:in `block in rip_notes'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleBackup.rb:163:in `each'
	from /Users/huyz/git/apple_cloud_notes_parser/lib/AppleBackup.rb:163:in `rip_notes'
	from notes_cloud_ripper.rb:128:in `<main>'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.