| 922 | # Verify file validity |
| 923 | # Return: None = Same as before, False = Invalid, True = Valid |
| 924 | def verifyFile(self, inner_path, file, ignore_same=True): |
| 925 | if inner_path.endswith("content.json"): # content.json: Check using sign |
| 926 | from Crypt import CryptBitcoin |
| 927 | try: |
| 928 | if type(file) is dict: |
| 929 | new_content = file |
| 930 | else: |
| 931 | if sys.version_info.major == 3 and sys.version_info.minor < 6: |
| 932 | new_content = json.loads(file.read().decode("utf8")) |
| 933 | else: |
| 934 | new_content = json.load(file) |
| 935 | if inner_path in self.contents: |
| 936 | old_content = self.contents.get(inner_path, {"modified": 0}) |
| 937 | # Checks if its newer the ours |
| 938 | if old_content["modified"] == new_content["modified"] and ignore_same: # Ignore, have the same content.json |
| 939 | return None |
| 940 | elif old_content["modified"] > new_content["modified"]: # We have newer |
| 941 | raise VerifyError( |
| 942 | "We have newer (Our: %s, Sent: %s)" % |
| 943 | (old_content["modified"], new_content["modified"]) |
| 944 | ) |
| 945 | if new_content["modified"] > time.time() + 60 * 60 * 24: # Content modified in the far future (allow 1 day+) |
| 946 | raise VerifyError("Modify timestamp is in the far future!") |
| 947 | if self.isArchived(inner_path, new_content["modified"]): |
| 948 | if inner_path in self.site.bad_files: |
| 949 | del self.site.bad_files[inner_path] |
| 950 | raise VerifyError("This file is archived!") |
| 951 | # Check sign |
| 952 | sign = new_content.get("sign") |
| 953 | signs = new_content.get("signs", {}) |
| 954 | if "sign" in new_content: |
| 955 | del(new_content["sign"]) # The file signed without the sign |
| 956 | if "signs" in new_content: |
| 957 | del(new_content["signs"]) # The file signed without the signs |
| 958 | |
| 959 | sign_content = json.dumps(new_content, sort_keys=True) # Dump the json to string to remove whitepsace |
| 960 | |
| 961 | # Fix float representation error on Android |
| 962 | modified = new_content["modified"] |
| 963 | if config.fix_float_decimals and type(modified) is float and not str(modified).endswith(".0"): |
| 964 | modified_fixed = "{:.6f}".format(modified).strip("0.") |
| 965 | sign_content = sign_content.replace( |
| 966 | '"modified": %s' % repr(modified), |
| 967 | '"modified": %s' % modified_fixed |
| 968 | ) |
| 969 | |
| 970 | if signs: # New style signing |
| 971 | valid_signers = self.getValidSigners(inner_path, new_content) |
| 972 | signs_required = self.getSignsRequired(inner_path, new_content) |
| 973 | |
| 974 | if inner_path == "content.json" and len(valid_signers) > 1: # Check signers_sign on root content.json |
| 975 | signers_data = "%s:%s" % (signs_required, ",".join(valid_signers)) |
| 976 | if not CryptBitcoin.verify(signers_data, self.site.address, new_content["signers_sign"]): |
| 977 | raise VerifyError("Invalid signers_sign!") |
| 978 | |
| 979 | if inner_path != "content.json" and not self.verifyCert(inner_path, new_content): # Check if cert valid |
| 980 | raise VerifyError("Invalid cert!") |
| 981 | |