{"action":"created","comment":{"url":"https://api.github.com/repos/williballenthin/python-registry/pulls/comments/62842321","id":62842321,"diff_hunk":"@@ -384,22 +405,38 @@ def validate_checksum(self):\n         \"\"\"\n         return self.calculate_checksum() == self.checksum()\n \n+    def validate(self):\n+        \"\"\"\n+        Are the file checksum and sequence numbers valid?\n+        Obsolete, use recovery_required instead.\n+        \"\"\"\n+        from warnings import warn\n+        warn(\"validate is obsolete, use recovery_required instead!\")\n+        return self.validate_checksum() and self.validate_sequence_numbers()\n+\n     def recovery_required(self):\n         \"\"\"\n         Are the file checksum and sequence numbers valid?\n-        Return a tuple with two boolean values:\n-          - the first one is True when the REGF block recovery is required,\n-          - the second one is True when data recovery is required.\n+        Return a named tuple with two boolean values:\n+          - the recover_header is True when the REGF block recovery is required,\n+          - the recover_data is True when data recovery is required.\n         \"\"\"\n+        recover = namedtuple('recover', ['recover_header', 'recover_data'])","path":"Registry/RegistryParse.py","position":null,"original_position":88,"commit_id":"ee433426b3f7be984f202e887b7877e3504185f5","original_commit_id":"ee433426b3f7be984f202e887b7877e3504185f5","user":{"login":"williballenthin","id":156560,"avatar_url":"https://avatars.githubusercontent.com/u/156560?v=3","gravatar_id":"","url":"https://api.github.com/users/williballenthin","html_url":"https://github.com/williballenthin","followers_url":"https://api.github.com/users/williballenthin/followers","following_url":"https://api.github.com/users/williballenthin/following{/other_user}","gists_url":"https://api.github.com/users/williballenthin/gists{/gist_id}","starred_url":"https://api.github.com/users/williballenthin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/williballenthin/subscriptions","organizations_url":"https://api.github.com/users/williballenthin/orgs","repos_url":"https://api.github.com/users/williballenthin/repos","events_url":"https://api.github.com/users/williballenthin/events{/privacy}","received_events_url":"https://api.github.com/users/williballenthin/received_events","type":"User","site_admin":false},"body":"I recommend creating the namedtuple definition at the top level of the file (rather than nested here), so users of the library can also create instances of the type, if they want.","created_at":"2016-05-11T12:56:30Z","updated_at":"2016-05-11T12:56:30Z","html_url":"https://github.com/williballenthin/python-registry/pull/61#discussion_r62842321","pull_request_url":"https://api.github.com/repos/williballenthin/python-registry/pulls/61","_links":{"self":{"href":"https://api.github.com/repos/williballenthin/python-registry/pulls/comments/62842321"},"html":{"href":"https://github.com/williballenthin/python-registry/pull/61#discussion_r62842321"},"pull_request":{"href":"https://api.github.com/repos/williballenthin/python-registry/pulls/61"}}},"pull_request":{"url":"https://api.github.com/repos/williballenthin/python-registry/pulls/61","id":67656654,"html_url":"https://github.com/williballenthin/python-registry/pull/61","diff_url":"https://github.com/williballenthin/python-registry/pull/61.diff","patch_url":"https://github.com/williballenthin/python-registry/pull/61.patch","issue_url":"https://api.github.com/repos/williballenthin/python-registry/issues/61","number":61,"state":"open","locked":false,"title":"Various updates and transaction log files support","user":{"login":"msuhanov","id":7497142,"avatar_url":"https://avatars.githubusercontent.com/u/7497142?v=3","gravatar_id":"","url":"https://api.github.com/users/msuhanov","html_url":"https://github.com/msuhanov","followers_url":"https://api.github.com/users/msuhanov/followers","following_url":"https://api.github.com/users/msuhanov/following{/other_user}","gists_url":"https://api.github.com/users/msuhanov/gists{/gist_id}","starred_url":"https://api.github.com/users/msuhanov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/msuhanov/subscriptions","organizations_url":"https://api.github.com/users/msuhanov/orgs","repos_url":"https://api.github.com/users/msuhanov/repos","events_url":"https://api.github.com/users/msuhanov/events{/privacy}","received_events_url":"https://api.github.com/users/msuhanov/received_events","type":"User","site_admin":false},"body":"Hello.\r\n\r\nThis pull request features various updates to the code of the primary file parser. The list of most important updates is:\r\n- The `REGFBlock` now has the `recovery_required()` method instead of the `validate()` method. This allows a library user to distinguish between 'header and data recovery required' and 'data recovery required' situations.\r\n- The `REGFBlock` also has the new `clustering_factor()`, `file_type()`, `is_primary_file()`, `is_old_transaction_log_file()`, `is_new_transaction_log_file()`, `file_format()` methods.\r\n- The `NKRecord`'s `has_classname()` method now relies on the class name length instead of the class name offset (according to [Joachim Metz](https://github.com/libyal/libregf/blob/master/documentation/Windows%20NT%20Registry%20File%20(REGF)%20format.asciidoc): \"The class name offset can also be 0 if not set. Seen in combination with a class name size of 0\").\r\n- The `NKRecord`'s `is_root()` method in now checking the bit mask 0x4 instead of a common value (0x2C).\r\n- The `HBINBlock`'s `last_hbin_offset()` method is now replaced with the `hbins_size()` method, because the corresponding field contains the size of all hbins, not the offset of the last hbin. The `has_next()` method was modified to use the `hbins_size()`.\r\n\r\nAlso, the support for the transaction log files (new format) has been implemented (the `RegistryLog` class). This is the must-have, because recent versions of Windows (Windows 8.1, Windows Server 2012 R2, and Windows 10) don't write all changes to the primary file immediately, but keep them in transaction log files up to an hour (by default). See the [Flush strategies in the Windows registry](https://github.com/msuhanov/regf-samples/blob/master/8.1-unreconciled/Flush%20strategies%20in%20the%20Windows%20registry.md).\r\n\r\nThe `RegistryLog` class accepts a file-like object of a primary file (and reads 512 bytes from it) and a file-like object or a file path of a transaction log file (and reads it in full). The class offers the `is_eligible_log()` method to check if a transaction log file can be applied and the `recover_hive()` method to apply log entries to a file-like object of a primary file. For the dual-logging scheme, the class offers the `recover_hive_continue()`, `is_starting_log()` methods to be used to perform the recovery in the same way as Windows does.\r\n\r\nAlso, the `TransactionLogFiles.py` script has been included along with five test cases. This script is an example of how to implement the recovery in the Windows way.\r\n\r\nFurther things to consider:\r\n- A forensic examiner might want to apply log entries step by step in order to examine old consistent states of a hive. Currently, all eligible log entries are applied at once.\r\n- Reading the whole transaction log file isn't good, because this file can be larger than a primary file.","created_at":"2016-04-25T01:17:01Z","updated_at":"2016-05-11T12:56:30Z","closed_at":null,"merged_at":null,"merge_commit_sha":"02c68cc63122853bfc70a66d3d0cb6d86122e603","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/williballenthin/python-registry/pulls/61/commits","review_comments_url":"https://api.github.com/repos/williballenthin/python-registry/pulls/61/comments","review_comment_url":"https://api.github.com/repos/williballenthin/python-registry/pulls/comments{/number}","comments_url":"https://api.github.com/repos/williballenthin/python-registry/issues/61/comments","statuses_url":"https://api.github.com/repos/williballenthin/python-registry/statuses/ee433426b3f7be984f202e887b7877e3504185f5","head":{"label":"msuhanov:master","ref":"master","sha":"ee433426b3f7be984f202e887b7877e3504185f5","user":{"login":"msuhanov","id":7497142,"avatar_url":"https://avatars.githubusercontent.com/u/7497142?v=3","gravatar_id":"","url":"https://api.github.com/users/msuhanov","html_url":"https://github.com/msuhanov","followers_url":"https://api.github.com/users/msuhanov/followers","following_url":"https://api.github.com/users/msuhanov/following{/other_user}","gists_url":"https://api.github.com/users/msuhanov/gists{/gist_id}","starred_url":"https://api.github.com/users/msuhanov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/msuhanov/subscriptions","organizations_url":"https://api.github.com/users/msuhanov/orgs","repos_url":"https://api.github.com/users/msuhanov/repos","events_url":"https://api.github.com/users/msuhanov/events{/privacy}","received_events_url":"https://api.github.com/users/msuhanov/received_events","type":"User","site_admin":false},"repo":{"id":55920596,"name":"python-registry","full_name":"msuhanov/python-registry","owner":{"login":"msuhanov","id":7497142,"avatar_url":"https://avatars.githubusercontent.com/u/7497142?v=3","gravatar_id":"","url":"https://api.github.com/users/msuhanov","html_url":"https://github.com/msuhanov","followers_url":"https://api.github.com/users/msuhanov/followers","following_url":"https://api.github.com/users/msuhanov/following{/other_user}","gists_url":"https://api.github.com/users/msuhanov/gists{/gist_id}","starred_url":"https://api.github.com/users/msuhanov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/msuhanov/subscriptions","organizations_url":"https://api.github.com/users/msuhanov/orgs","repos_url":"https://api.github.com/users/msuhanov/repos","events_url":"https://api.github.com/users/msuhanov/events{/privacy}","received_events_url":"https://api.github.com/users/msuhanov/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/msuhanov/python-registry","description":"Read access to Windows Registry files.","fork":true,"url":"https://api.github.com/repos/msuhanov/python-registry","forks_url":"https://api.github.com/repos/msuhanov/python-registry/forks","keys_url":"https://api.github.com/repos/msuhanov/python-registry/keys{/key_id}","collaborators_url":"https://api.github.com/repos/msuhanov/python-registry/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/msuhanov/python-registry/teams","hooks_url":"https://api.github.com/repos/msuhanov/python-registry/hooks","issue_events_url":"https://api.github.com/repos/msuhanov/python-registry/issues/events{/number}","events_url":"https://api.github.com/repos/msuhanov/python-registry/events","assignees_url":"https://api.github.com/repos/msuhanov/python-registry/assignees{/user}","branches_url":"https://api.github.com/repos/msuhanov/python-registry/branches{/branch}","tags_url":"https://api.github.com/repos/msuhanov/python-registry/tags","blobs_url":"https://api.github.com/repos/msuhanov/python-registry/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/msuhanov/python-registry/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/msuhanov/python-registry/git/refs{/sha}","trees_url":"https://api.github.com/repos/msuhanov/python-registry/git/trees{/sha}","statuses_url":"https://api.github.com/repos/msuhanov/python-registry/statuses/{sha}","languages_url":"https://api.github.com/repos/msuhanov/python-registry/languages","stargazers_url":"https://api.github.com/repos/msuhanov/python-registry/stargazers","contributors_url":"https://api.github.com/repos/msuhanov/python-registry/contributors","subscribers_url":"https://api.github.com/repos/msuhanov/python-registry/subscribers","subscription_url":"https://api.github.com/repos/msuhanov/python-registry/subscription","commits_url":"https://api.github.com/repos/msuhanov/python-registry/commits{/sha}","git_commits_url":"https://api.github.com/repos/msuhanov/python-registry/git/commits{/sha}","comments_url":"https://api.github.com/repos/msuhanov/python-registry/comments{/number}","issue_comment_url":"https://api.github.com/repos/msuhanov/python-registry/issues/comments{/number}","contents_url":"https://api.github.com/repos/msuhanov/python-registry/contents/{+path}","compare_url":"https://api.github.com/repos/msuhanov/python-registry/compare/{base}...{head}","merges_url":"https://api.github.com/repos/msuhanov/python-registry/merges","archive_url":"https://api.github.com/repos/msuhanov/python-registry/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/msuhanov/python-registry/downloads","issues_url":"https://api.github.com/repos/msuhanov/python-registry/issues{/number}","pulls_url":"https://api.github.com/repos/msuhanov/python-registry/pulls{/number}","milestones_url":"https://api.github.com/repos/msuhanov/python-registry/milestones{/number}","notifications_url":"https://api.github.com/repos/msuhanov/python-registry/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/msuhanov/python-registry/labels{/name}","releases_url":"https://api.github.com/repos/msuhanov/python-registry/releases{/id}","deployments_url":"https://api.github.com/repos/msuhanov/python-registry/deployments","created_at":"2016-04-10T20:22:10Z","updated_at":"2016-04-10T20:22:13Z","pushed_at":"2016-05-10T10:29:33Z","git_url":"git://github.com/msuhanov/python-registry.git","ssh_url":"git@github.com:msuhanov/python-registry.git","clone_url":"https://github.com/msuhanov/python-registry.git","svn_url":"https://github.com/msuhanov/python-registry","homepage":"http://www.williballenthin.com/registry/","size":2805,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"williballenthin:master","ref":"master","sha":"20f3ebe1d873b6345fdf9cca55af9c31c46f8551","user":{"login":"williballenthin","id":156560,"avatar_url":"https://avatars.githubusercontent.com/u/156560?v=3","gravatar_id":"","url":"https://api.github.com/users/williballenthin","html_url":"https://github.com/williballenthin","followers_url":"https://api.github.com/users/williballenthin/followers","following_url":"https://api.github.com/users/williballenthin/following{/other_user}","gists_url":"https://api.github.com/users/williballenthin/gists{/gist_id}","starred_url":"https://api.github.com/users/williballenthin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/williballenthin/subscriptions","organizations_url":"https://api.github.com/users/williballenthin/orgs","repos_url":"https://api.github.com/users/williballenthin/repos","events_url":"https://api.github.com/users/williballenthin/events{/privacy}","received_events_url":"https://api.github.com/users/williballenthin/received_events","type":"User","site_admin":false},"repo":{"id":1746585,"name":"python-registry","full_name":"williballenthin/python-registry","owner":{"login":"williballenthin","id":156560,"avatar_url":"https://avatars.githubusercontent.com/u/156560?v=3","gravatar_id":"","url":"https://api.github.com/users/williballenthin","html_url":"https://github.com/williballenthin","followers_url":"https://api.github.com/users/williballenthin/followers","following_url":"https://api.github.com/users/williballenthin/following{/other_user}","gists_url":"https://api.github.com/users/williballenthin/gists{/gist_id}","starred_url":"https://api.github.com/users/williballenthin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/williballenthin/subscriptions","organizations_url":"https://api.github.com/users/williballenthin/orgs","repos_url":"https://api.github.com/users/williballenthin/repos","events_url":"https://api.github.com/users/williballenthin/events{/privacy}","received_events_url":"https://api.github.com/users/williballenthin/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/williballenthin/python-registry","description":"Read access to Windows Registry files.","fork":false,"url":"https://api.github.com/repos/williballenthin/python-registry","forks_url":"https://api.github.com/repos/williballenthin/python-registry/forks","keys_url":"https://api.github.com/repos/williballenthin/python-registry/keys{/key_id}","collaborators_url":"https://api.github.com/repos/williballenthin/python-registry/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/williballenthin/python-registry/teams","hooks_url":"https://api.github.com/repos/williballenthin/python-registry/hooks","issue_events_url":"https://api.github.com/repos/williballenthin/python-registry/issues/events{/number}","events_url":"https://api.github.com/repos/williballenthin/python-registry/events","assignees_url":"https://api.github.com/repos/williballenthin/python-registry/assignees{/user}","branches_url":"https://api.github.com/repos/williballenthin/python-registry/branches{/branch}","tags_url":"https://api.github.com/repos/williballenthin/python-registry/tags","blobs_url":"https://api.github.com/repos/williballenthin/python-registry/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/williballenthin/python-registry/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/williballenthin/python-registry/git/refs{/sha}","trees_url":"https://api.github.com/repos/williballenthin/python-registry/git/trees{/sha}","statuses_url":"https://api.github.com/repos/williballenthin/python-registry/statuses/{sha}","languages_url":"https://api.github.com/repos/williballenthin/python-registry/languages","stargazers_url":"https://api.github.com/repos/williballenthin/python-registry/stargazers","contributors_url":"https://api.github.com/repos/williballenthin/python-registry/contributors","subscribers_url":"https://api.github.com/repos/williballenthin/python-registry/subscribers","subscription_url":"https://api.github.com/repos/williballenthin/python-registry/subscription","commits_url":"https://api.github.com/repos/williballenthin/python-registry/commits{/sha}","git_commits_url":"https://api.github.com/repos/williballenthin/python-registry/git/commits{/sha}","comments_url":"https://api.github.com/repos/williballenthin/python-registry/comments{/number}","issue_comment_url":"https://api.github.com/repos/williballenthin/python-registry/issues/comments{/number}","contents_url":"https://api.github.com/repos/williballenthin/python-registry/contents/{+path}","compare_url":"https://api.github.com/repos/williballenthin/python-registry/compare/{base}...{head}","merges_url":"https://api.github.com/repos/williballenthin/python-registry/merges","archive_url":"https://api.github.com/repos/williballenthin/python-registry/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/williballenthin/python-registry/downloads","issues_url":"https://api.github.com/repos/williballenthin/python-registry/issues{/number}","pulls_url":"https://api.github.com/repos/williballenthin/python-registry/pulls{/number}","milestones_url":"https://api.github.com/repos/williballenthin/python-registry/milestones{/number}","notifications_url":"https://api.github.com/repos/williballenthin/python-registry/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/williballenthin/python-registry/labels{/name}","releases_url":"https://api.github.com/repos/williballenthin/python-registry/releases{/id}","deployments_url":"https://api.github.com/repos/williballenthin/python-registry/deployments","created_at":"2011-05-14T05:16:19Z","updated_at":"2016-05-09T16:48:07Z","pushed_at":"2016-05-10T21:13:32Z","git_url":"git://github.com/williballenthin/python-registry.git","ssh_url":"git@github.com:williballenthin/python-registry.git","clone_url":"https://github.com/williballenthin/python-registry.git","svn_url":"https://github.com/williballenthin/python-registry","homepage":"http://www.williballenthin.com/registry/","size":2923,"stargazers_count":101,"watchers_count":101,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":29,"mirror_url":null,"open_issues_count":10,"forks":29,"open_issues":10,"watchers":101,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/williballenthin/python-registry/pulls/61"},"html":{"href":"https://github.com/williballenthin/python-registry/pull/61"},"issue":{"href":"https://api.github.com/repos/williballenthin/python-registry/issues/61"},"comments":{"href":"https://api.github.com/repos/williballenthin/python-registry/issues/61/comments"},"review_comments":{"href":"https://api.github.com/repos/williballenthin/python-registry/pulls/61/comments"},"review_comment":{"href":"https://api.github.com/repos/williballenthin/python-registry/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/williballenthin/python-registry/pulls/61/commits"},"statuses":{"href":"https://api.github.com/repos/williballenthin/python-registry/statuses/ee433426b3f7be984f202e887b7877e3504185f5"}}}}