diff --git a/cell/api.js b/cell/api.js index 9a68b40e91..1ada44896c 100644 --- a/cell/api.js +++ b/cell/api.js @@ -7068,7 +7068,7 @@ var editor; password: arr[i].temporaryPassword, salt: arr[i].saltValue, spinCount: arr[i].spinCount, - alg: AscCommonExcel.fromModelAlgoritmName(arr[i].algorithmName) + alg: AscCommon.fromModelAlgorithmName(arr[i].algorithmName) }); } } @@ -7297,7 +7297,7 @@ var editor; checkPassword([AscCommonExcel.getPasswordHash(props.temporaryPassword, true)]); } else { var checkHash = {password: props.temporaryPassword, salt: props.saltValue, spinCount: props.spinCount, - alg: AscCommonExcel.fromModelAlgoritmName(props.algorithmName)}; + alg: AscCommon.fromModelAlgorithmName(props.algorithmName)}; AscCommon.calculateProtectHash([checkHash], checkPassword); } } else { @@ -7412,7 +7412,7 @@ var editor; checkPassword([AscCommonExcel.getPasswordHash(props.temporaryPassword, true)]); } else { var checkHash = {password: props.temporaryPassword, salt: props.workbookSaltValue, spinCount: props.workbookSpinCount, - alg: AscCommonExcel.fromModelAlgoritmName(props.workbookAlgorithmName)}; + alg: AscCommon.fromModelAlgorithmName(props.algorithmName)}; AscCommon.calculateProtectHash([checkHash], checkPassword); } } else { diff --git a/cell/model/Workbook.js b/cell/model/Workbook.js index 6ee84038b8..730b794150 100644 --- a/cell/model/Workbook.js +++ b/cell/model/Workbook.js @@ -10964,7 +10964,7 @@ password: val, salt: this.aProtectedRanges[i].saltValue, spinCount: this.aProtectedRanges[i].spinCount, - alg: AscCommonExcel.fromModelAlgoritmName(this.aProtectedRanges[i].algorithmName) + alg: AscCommon.fromModelAlgorithmName(this.aProtectedRanges[i].algorithmName) }); } } diff --git a/cell/model/WorkbookProtection.js b/cell/model/WorkbookProtection.js index 0ddff4edd9..e9eeb042d3 100644 --- a/cell/model/WorkbookProtection.js +++ b/cell/model/WorkbookProtection.js @@ -52,86 +52,38 @@ this.pivotTables = true; this.selectUnlockedCells = false;*/ - var c_oSerProtectedAlgorithmNameTypes = { - MD2: 1, - MD4: 2, - MD5: 3, - RIPEMD_128: 4, - RIPEMD_160: 5, - SHA_1: 6, - SHA_256: 7, - SHA_384: 8, - SHA_512: 9, - WHIRLPOOL: 10 - }; - - function fromModelAlgoritmName(alg) { - switch (alg) { - case c_oSerProtectedAlgorithmNameTypes.MD2 : - alg = AscCommon.HashAlgs.MD2; - break; - case c_oSerProtectedAlgorithmNameTypes.MD4 : - alg = AscCommon.HashAlgs.MD4; - break; - case c_oSerProtectedAlgorithmNameTypes.MD5 : - alg = AscCommon.HashAlgs.MD5; - break; - case c_oSerProtectedAlgorithmNameTypes.RIPEMD_160 : - alg = AscCommon.HashAlgs.RMD160; - break; - case c_oSerProtectedAlgorithmNameTypes.SHA_1 : - alg = AscCommon.HashAlgs.SHA1; - break; - case c_oSerProtectedAlgorithmNameTypes.SHA_256 : - alg = AscCommon.HashAlgs.SHA256; - break; - case c_oSerProtectedAlgorithmNameTypes.SHA_384 : - alg = AscCommon.HashAlgs.SHA384; - break; - case c_oSerProtectedAlgorithmNameTypes.SHA_512 : - alg = AscCommon.HashAlgs.SHA512; - break; - case c_oSerProtectedAlgorithmNameTypes.WHIRLPOOL : - alg = AscCommon.HashAlgs.WHIRLPOOL; - break; - default: - alg = AscCommon.HashAlgs.SHA256; - } - return alg; - } - function FromXml_ST_AlgorithmName(str) { var alg = null; switch (str) { case "MD2" : - alg = c_oSerProtectedAlgorithmNameTypes.MD2; + alg = AscCommon.c_oSerAlgorithmNameTypes.MD2; break; case "MD4" : - alg = c_oSerProtectedAlgorithmNameTypes.MD4; + alg = AscCommon.c_oSerAlgorithmNameTypes.MD4; break; case "MD5" : - alg = c_oSerProtectedAlgorithmNameTypes.MD5; + alg = AscCommon.c_oSerAlgorithmNameTypes.MD5; break; case "RIPEMD-128" : - alg = c_oSerProtectedAlgorithmNameTypes.RIPEMD_128; + alg = AscCommon.c_oSerAlgorithmNameTypes.RIPEMD_128; break; case "RIPEMD-160" : - alg = c_oSerProtectedAlgorithmNameTypes.RIPEMD_160; + alg = AscCommon.c_oSerAlgorithmNameTypes.RIPEMD_160; break; case "SHA-1" : - alg = c_oSerProtectedAlgorithmNameTypes.SHA1; + alg = AscCommon.c_oSerAlgorithmNameTypes.SHA1; break; case "SHA-256" : - alg = c_oSerProtectedAlgorithmNameTypes.SHA_256; + alg = AscCommon.c_oSerAlgorithmNameTypes.SHA_256; break; case "SHA-384" : - alg = c_oSerProtectedAlgorithmNameTypes.SHA_384; + alg = AscCommon.c_oSerAlgorithmNameTypes.SHA_384; break; case "SHA-512" : - alg = c_oSerProtectedAlgorithmNameTypes.SHA_512; + alg = AscCommon.c_oSerAlgorithmNameTypes.SHA_512; break; case "WHIRLPOOL" : - alg = c_oSerProtectedAlgorithmNameTypes.WHIRLPOOL; + alg = AscCommon.c_oSerAlgorithmNameTypes.WHIRLPOOL; break; } return alg; @@ -140,45 +92,40 @@ function ToXml_ST_AlgorithmName(alg) { var str = null; switch (alg) { - case c_oSerProtectedAlgorithmNameTypes.MD2: + case AscCommon.c_oSerAlgorithmNameTypes.MD2: str = "MD2"; break; - case c_oSerProtectedAlgorithmNameTypes.MD4: + case AscCommon.c_oSerAlgorithmNameTypes.MD4: str = "MD4"; break; - case c_oSerProtectedAlgorithmNameTypes.MD5: + case AscCommon.c_oSerAlgorithmNameTypes.MD5: str = "MD5"; break; - case c_oSerProtectedAlgorithmNameTypes.RIPEMD_128: + case AscCommon.c_oSerAlgorithmNameTypes.RIPEMD_128: str = "RIPEMD-128"; break; - case c_oSerProtectedAlgorithmNameTypes.RIPEMD_160: + case AscCommon.c_oSerAlgorithmNameTypes.RIPEMD_160: str = "RIPEMD-160"; break; - case c_oSerProtectedAlgorithmNameTypes.SHA1: + case AscCommon.c_oSerAlgorithmNameTypes.SHA1: str = "SHA-1"; break; - case c_oSerProtectedAlgorithmNameTypes.SHA_256 : + case AscCommon.c_oSerAlgorithmNameTypes.SHA_256 : str = "SHA-256"; break; - case c_oSerProtectedAlgorithmNameTypes.SHA_384 : + case AscCommon.c_oSerAlgorithmNameTypes.SHA_384 : str = "SHA-384"; break; - case c_oSerProtectedAlgorithmNameTypes.SHA_512: + case AscCommon.c_oSerAlgorithmNameTypes.SHA_512: str = "SHA-512"; break; - case c_oSerProtectedAlgorithmNameTypes.WHIRLPOOL: + case AscCommon.c_oSerAlgorithmNameTypes.WHIRLPOOL: str = "WHIRLPOOL"; break; } return str; } - - function generateHashParams() { - return {spinCount: 100000, saltValue: AscCommon.randomBytes(16).base64(), algorithmName: c_oSerProtectedAlgorithmNameTypes.SHA_512}; - } - function getPasswordHash(password, getString) { var nResult = null; if (password.length) { @@ -573,10 +520,10 @@ //просталяю временный пароль, аспинхронная проверка пароля в asc_setProtectedSheet this.setSheet(!this.sheet); if (this.sheet && password) { - var hashParams = generateHashParams(); + var hashParams = AscCommon.generateHashParams(); this.saltValue = hashParams.saltValue; this.spinCount = hashParams.spinCount; - this.algorithmName = hashParams.algorithmName; + this.algorithmName = AscCommon.c_oSerAlgorithmNameTypes.SHA_512; } this.temporaryPassword = password; if (callback) { @@ -877,10 +824,10 @@ this.setLockStructure(!this.lockStructure); if (this.lockStructure && password) { - var hashParams = generateHashParams(); + var hashParams = AscCommon.generateHashParams(); this.workbookSaltValue = hashParams.saltValue; this.workbookSpinCount = hashParams.spinCount; - this.workbookAlgorithmName = hashParams.algorithmName; + this.workbookAlgorithmName = AscCommon.c_oSerAlgorithmNameTypes.SHA_512; } this.temporaryPassword = password; if (callback) { @@ -1316,10 +1263,10 @@ }; CProtectedRange.prototype.asc_setPassword = function (val) { if (val) { - var hashParams = generateHashParams(); + var hashParams = AscCommon.generateHashParams(); this.saltValue = hashParams.saltValue; this.spinCount = hashParams.spinCount; - this.algorithmName = hashParams.algorithmName; + this.algorithmName = AscCommon.c_oSerAlgorithmNameTypes.SHA_512; } //генерируем хэш this.temporaryPassword = val; @@ -1331,7 +1278,7 @@ return this.isLock; }; CProtectedRange.prototype.asc_checkPassword = function (val, callback) { - var checkHash = {password: val, salt: this.saltValue, spinCount: this.spinCount, alg: fromModelAlgoritmName(this.algorithmName)}; + var checkHash = {password: val, salt: this.saltValue, spinCount: this.spinCount, alg: AscCommon.fromModelAlgorithmName(this.algorithmName)}; AscCommon.calculateProtectHash([checkHash], function (hash) { callback(hash && hash[0] === this.hashValue); }); @@ -1439,7 +1386,6 @@ prot["asc_checkPassword"] = prot.asc_checkPassword; prot["asc_getId"] = prot.asc_getId; - window["AscCommonExcel"].fromModelAlgoritmName = fromModelAlgoritmName; window["AscCommonExcel"].getPasswordHash = getPasswordHash; window["AscCommonExcel"].FromXml_ST_AlgorithmName = FromXml_ST_AlgorithmName; window["AscCommonExcel"].ToXml_ST_AlgorithmName = ToXml_ST_AlgorithmName; diff --git a/common/HistoryCommon.js b/common/HistoryCommon.js index 2c8f2099c0..29935cbcfc 100644 --- a/common/HistoryCommon.js +++ b/common/HistoryCommon.js @@ -4359,6 +4359,7 @@ window['AscDFH'].historydescription_Document_CorrectFormTextByFormat = 0x0196; window['AscDFH'].historydescription_Document_CorrectEnterText = 0x0197; window['AscDFH'].historydescription_Document_ConvertMathView = 0x0198; + window['AscDFH'].historydescription_Document_DocumentProtection = 0x0198; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/common/SerializeCommonWordExcel.js b/common/SerializeCommonWordExcel.js index 7c51a4b7c9..9366e6a9ab 100644 --- a/common/SerializeCommonWordExcel.js +++ b/common/SerializeCommonWordExcel.js @@ -135,6 +135,35 @@ var c_oSerShdType = { nodeAttributeEnd: 0xFB }; + var c_oSerAlgorithmNameTypes = { + MD2: 1, + MD4: 2, + MD5: 3, + RIPEMD_128: 4, + RIPEMD_160: 5, + SHA_1: 6, + SHA_256: 7, + SHA_384: 8, + SHA_512: 9, + WHIRLPOOL: 10 + }; + + var c_oSerCryptAlgorithmSid = { + MD2: 1, + MD4: 2, + MD5: 3, + SHA_1: 4, + MAC: 5, + RIPEMD: 6, + RIPEMD_160: 7, + //SHA_384: 8, + HMAC: 9, + SHA_256: 12, + SHA_384: 13, + SHA_512: 14, + }; + + function BinaryCommonWriter(memory) { this.memory = memory; @@ -1532,4 +1561,8 @@ function isRealObject(obj) window['AscCommon'].GetStringUtf8 = GetStringUtf8; window['AscCommon'].g_nodeAttributeStart = c_nodeAttribute.nodeAttributeStart; window['AscCommon'].g_nodeAttributeEnd = c_nodeAttribute.nodeAttributeEnd; + window['AscCommon'].c_oSerAlgorithmNameTypes = c_oSerAlgorithmNameTypes; + window['AscCommon'].c_oSerCryptAlgorithmSid = c_oSerCryptAlgorithmSid; + + })(window); diff --git a/common/commonDefines.js b/common/commonDefines.js index 13670fd5a2..e7af10f334 100644 --- a/common/commonDefines.js +++ b/common/commonDefines.js @@ -2347,6 +2347,7 @@ var lcid_haLatn = 0x7c68; // Hausa, Latin var changestype_Document_Settings = 77; // Изменение общих настроек документа Document.Settings var changestype_Timing = 78; var changestype_ViewPr = 79; + var changestype_DocumentProtection = 80; var changestype_2_InlineObjectMove = 1; // Передвигаем объект в заданную позцию (проверяем место, в которое пытаемся передвинуть) var changestype_2_HdrFtr = 2; // Изменения с колонтитулом @@ -4341,6 +4342,7 @@ var lcid_haLatn = 0x7c68; // Hausa, Latin window["AscCommon"].changestype_Document_Settings = changestype_Document_Settings; window["AscCommon"].changestype_Timing = changestype_Timing; window["AscCommon"].changestype_ViewPr = changestype_ViewPr; + window["AscCommon"].changestype_DocumentProtection = changestype_DocumentProtection; window["AscCommon"].changestype_2_InlineObjectMove = changestype_2_InlineObjectMove; window["AscCommon"].changestype_2_HdrFtr = changestype_2_HdrFtr; diff --git a/common/editorscommon.js b/common/editorscommon.js index 1a8ed9c2df..9a8033704b 100644 --- a/common/editorscommon.js +++ b/common/editorscommon.js @@ -12926,6 +12926,85 @@ return sAction.indexOf("ppaction://hlink") === 0; } + function generateHashParams() { + return {spinCount: 100000, saltValue: AscCommon.randomBytes(16).base64()}; + } + + function fromModelAlgorithmName(alg) { + switch (alg) { + case AscCommon.c_oSerAlgorithmNameTypes.MD2 : + alg = AscCommon.HashAlgs.MD2; + break; + case AscCommon.c_oSerAlgorithmNameTypes.MD4 : + alg = AscCommon.HashAlgs.MD4; + break; + case AscCommon.c_oSerAlgorithmNameTypes.MD5 : + alg = AscCommon.HashAlgs.MD5; + break; + case AscCommon.c_oSerAlgorithmNameTypes.RIPEMD_160 : + alg = AscCommon.HashAlgs.RMD160; + break; + case AscCommon.c_oSerAlgorithmNameTypes.SHA_1 : + alg = AscCommon.HashAlgs.SHA1; + break; + case AscCommon.c_oSerAlgorithmNameTypes.SHA_256 : + alg = AscCommon.HashAlgs.SHA256; + break; + case AscCommon.c_oSerAlgorithmNameTypes.SHA_384 : + alg = AscCommon.HashAlgs.SHA384; + break; + case AscCommon.c_oSerAlgorithmNameTypes.SHA_512 : + alg = AscCommon.HashAlgs.SHA512; + break; + case AscCommon.c_oSerAlgorithmNameTypes.WHIRLPOOL : + alg = AscCommon.HashAlgs.WHIRLPOOL; + break; + default: + alg = AscCommon.HashAlgs.SHA256; + } + return alg; + } + + function fromModelCryptAlgorithmSid(alg) { + var res = null; + switch (alg) { + case AscCommon.c_oSerCryptAlgorithmSid.MD2 : + res = AscCommon.HashAlgs.MD2; + break; + case AscCommon.c_oSerCryptAlgorithmSid.MD4 : + res = AscCommon.HashAlgs.MD4; + break; + case AscCommon.c_oSerCryptAlgorithmSid.MD5 : + res = AscCommon.HashAlgs.MD5; + break; + case AscCommon.c_oSerCryptAlgorithmSid.SHA_1 : + res = AscCommon.HashAlgs.SHA1; + break; + case AscCommon.c_oSerCryptAlgorithmSid.MAC : + //alg = AscCommon.HashAlgs.SHA1; + break; + case AscCommon.c_oSerCryptAlgorithmSid.RIPEMD : + //alg = AscCommon.HashAlgs.SHA256; + break; + case AscCommon.c_oSerCryptAlgorithmSid.RIPEMD_160 : + //alg = AscCommon.HashAlgs.SHA384; + break; + case AscCommon.c_oSerCryptAlgorithmSid.HMAC : + //alg = AscCommon.HashAlgs.SHA512; + break; + case AscCommon.c_oSerCryptAlgorithmSid.SHA_256 : + res = AscCommon.HashAlgs.SHA256; + break; + case AscCommon.c_oSerCryptAlgorithmSid.SHA_384 : + res = AscCommon.HashAlgs.SHA384; + break; + case AscCommon.c_oSerCryptAlgorithmSid.SHA_512 : + res = AscCommon.HashAlgs.SHA512; + break; + } + return res; + } + //------------------------------------------------------------export--------------------------------------------------- window['AscCommon'] = window['AscCommon'] || {}; window["AscCommon"].getSockJs = getSockJs; @@ -13103,6 +13182,9 @@ window['AscCommon'].g_oCRC32 = g_oCRC32; window["AscCommon"].RangeTopBottomIterator = RangeTopBottomIterator; window["AscCommon"].IsLinkPPAction = IsLinkPPAction; + window["AscCommon"].generateHashParams = generateHashParams; + window["AscCommon"].fromModelAlgorithmName = fromModelAlgorithmName; + window["AscCommon"].fromModelCryptAlgorithmSid = fromModelCryptAlgorithmSid; })(window); window["asc_initAdvancedOptions"] = function(_code, _file_hash, _docInfo) diff --git a/common/hash/hash.js b/common/hash/hash.js index 84748a84db..a66d7bead4 100644 --- a/common/hash/hash.js +++ b/common/hash/hash.js @@ -142,6 +142,114 @@ currentHashWorker = new CHashWorker(sendedData, callback); }; + window['AscCommon'].prepareWordPassword = function(password) { + + let _highOrderWords = [[0xE1, 0xF0], [0x1D, 0x0F], [0xCC, 0x9C], [0x84, 0xC0], [0x11, 0x0C], [0x0E, 0x10], [0xF1, 0xCE], [0x31, 0x3E], [0x18, 0x72], [0xE1, 0x39], + [0xD4, 0x0F], [0x84, 0xF9], [0x28, 0x0C], [0xA9, 0x6A], [0x4E, 0xC3]]; + + let _encryptionMatrix = [[[0xAE, 0xFC], [0x4D, 0xD9], [0x9B, 0xB2], [0x27, 0x45], [0x4E, 0x8A], [0x9D, 0x14], [0x2A, 0x09]], + [[0x7B, 0x61], [0xF6, 0xC2], [0xFD, 0xA5], [0xEB, 0x6B], [0xC6, 0xF7], [0x9D, 0xCF], [0x2B, 0xBF]], + [[0x45, 0x63], [0x8A, 0xC6], [0x05, 0xAD], [0x0B, 0x5A], [0x16, 0xB4], [0x2D, 0x68], [0x5A, 0xD0]], + [[0x03, 0x75], [0x06, 0xEA], [0x0D, 0xD4], [0x1B, 0xA8], [0x37, 0x50], [0x6E, 0xA0], [0xDD, 0x40]], + [[0xD8, 0x49], [0xA0, 0xB3], [0x51, 0x47], [0xA2, 0x8E], [0x55, 0x3D], [0xAA, 0x7A], [0x44, 0xD5]], + [[0x6F, 0x45], [0xDE, 0x8A], [0xAD, 0x35], [0x4A, 0x4B], [0x94, 0x96], [0x39, 0x0D], [0x72, 0x1A]], + [[0xEB, 0x23], [0xC6, 0x67], [0x9C, 0xEF], [0x29, 0xFF], [0x53, 0xFE], [0xA7, 0xFC], [0x5F, 0xD9]], + [[0x47, 0xD3], [0x8F, 0xA6], [0x0F, 0x6D], [0x1E, 0xDA], [0x3D, 0xB4], [0x7B, 0x68], [0xF6, 0xD0]], + [[0xB8, 0x61], [0x60, 0xE3], [0xC1, 0xC6], [0x93, 0xAD], [0x37, 0x7B], [0x6E, 0xF6], [0xDD, 0xEC]], + [[0x45, 0xA0], [0x8B, 0x40], [0x06, 0xA1], [0x0D, 0x42], [0x1A, 0x84], [0x35, 0x08], [0x6A, 0x10]], + [[0xAA, 0x51], [0x44, 0x83], [0x89, 0x06], [0x02, 0x2D], [0x04, 0x5A], [0x08, 0xB4], [0x11, 0x68]], + [[0x76, 0xB4], [0xED, 0x68], [0xCA, 0xF1], [0x85, 0xC3], [0x1B, 0xA7], [0x37, 0x4E], [0x6E, 0x9C]], + [[0x37, 0x30], [0x6E, 0x60], [0xDC, 0xC0], [0xA9, 0xA1], [0x43, 0x63], [0x86, 0xC6], [0x1D, 0xAD]], + [[0x33, 0x31], [0x66, 0x62], [0xCC, 0xC4], [0x89, 0xA9], [0x03, 0x73], [0x06, 0xE6], [0x0D, 0xCC]], + [[0x10, 0x21], [0x20, 0x42], [0x40, 0x84], [0x81, 0x08], [0x12, 0x31], [0x24, 0x62], [0x48, 0xC4]]]; + + let byteToBits = function (byte) { + let bitsArr = []; + for (let i = 0; i < 8; i++) { + let bit = byte & (1 << i) ? 1 : 0; + bitsArr.push(bit); + } + return bitsArr; + }; + + let splitByHighLowBytes = function (val) { + return [(val & 0xff00) >> 8, val & 0x00ff]; + }; + + let getHexStr = function (arr) { + let res = ""; + for (let i = 0; i < arr.length; i++) { + res += AscCommon.ByteToHex(arr[i]); + } + return res; + }; + + let getUnionBytes = function (byte1, byte2) { + return ((byte1 << 8) | byte2); + }; + + if (password == null) { + return null; + } + + let textEncoder = new TextEncoder(); + let passwordBytes = textEncoder.encode(password); + + let maxPasswordLength = 15; + passwordBytes = passwordBytes.slice(0, maxPasswordLength); + let passwordLength = passwordBytes.length; + + //high word + let highOrderWord = [0x00, 0x00]; + if (passwordLength > 0) { + highOrderWord = _highOrderWords[passwordLength - 1]; + } + for (var i = 0; i < passwordLength; i++) { + let passwordByte = passwordBytes[i]; + let encryptionMatrixIndex = i + (_encryptionMatrix.length - passwordLength); + + let bitArray = byteToBits(passwordByte); + + for (let j = 0; j < _encryptionMatrix[0].length; j++) { + let isSet = bitArray[j]; + + if (isSet) { + for (let k = 0; k < _encryptionMatrix[0][0].length; k++) { + highOrderWord[k] = highOrderWord[k] ^ _encryptionMatrix[encryptionMatrixIndex][j][k]; + } + } + } + } + + if (!highOrderWord) { + return null; + } + + //low word + let lowOrderSequence = 0x00; + let sequence1 = 0x01; + let sequence7FFF = 0x7FFF; + for (let i = passwordLength - 1; i >= 0; i--) { + let passwordByte = passwordBytes[i]; + lowOrderSequence = (((lowOrderSequence >> 14) & sequence1) | ((lowOrderSequence << 1) & sequence7FFF)) ^ passwordByte; + } + lowOrderSequence = (((lowOrderSequence >> 14) & sequence1) | ((lowOrderSequence << 1) & sequence7FFF)) ^ passwordLength ^ getUnionBytes(0xCE, 0x4B); + + let lowOrderWord = splitByHighLowBytes(lowOrderSequence); + if (!lowOrderWord) { + return null; + } + + //full word + let fullWord = highOrderWord.concat(lowOrderWord); + fullWord = fullWord && fullWord.reverse(); + if (!fullWord) { + return null; + } + + return getHexStr(fullWord); + }; + window['AscCommon'].HashAlgs = { MD2 : 0, MD4 : 1, diff --git a/configs/word.json b/configs/word.json index a274be8823..36f4a5c66d 100644 --- a/configs/word.json +++ b/configs/word.json @@ -54,6 +54,7 @@ "common/stringserialize.js", "common/random.js", + "common/hash/hash.js", "common/Drawings/Metafile.js", "common/libfont/textmeasurer.js", diff --git a/word/Editor/CollaborativeEditing.js b/word/Editor/CollaborativeEditing.js index 6bebecbece..97fb06a7d3 100644 --- a/word/Editor/CollaborativeEditing.js +++ b/word/Editor/CollaborativeEditing.js @@ -204,6 +204,8 @@ CWordCollaborativeEditing.prototype.Release_Locks = function() editor.sync_UnLockDocumentSchema(); else if (this.m_aNeedUnlock[Index] instanceof AscCommon.CCore) editor.sendEvent("asc_onLockCore", false); + else if (this.m_aNeedUnlock[Index] instanceof AscCommonWord.CDocProtect) + editor.sendEvent("asc_onLockDocumentProtection", false); } else if (AscCommon.locktype_Other3 === CurLockType) { diff --git a/word/Editor/Document.js b/word/Editor/Document.js index a8131b31af..18f9b21f79 100644 --- a/word/Editor/Document.js +++ b/word/Editor/Document.js @@ -13553,6 +13553,13 @@ CDocument.prototype.private_DocumentIsSelectionLocked = function(CheckType) this.Core.Lock.Check(this.Core.Get_Id()); } } + else if (AscCommon.changestype_DocumentProtection === CheckType) + { + if (this.Settings.DocumentProtection) + { + this.Settings.DocumentProtection.Lock.Check(this.Settings.DocumentProtection.Get_Id()); + } + } else if (AscCommon.changestype_Document_Settings === CheckType) { this.Lock.Check(this.GetId()); @@ -16668,6 +16675,13 @@ CDocument.prototype.IsSpecialFormsSettingsDefault = function() { return this.Settings.SpecialFormsSettings.IsDefault(); }; +CDocument.prototype.SetProtection = function(props) +{ + if (this.Settings.DocumentProtection) { + this.Settings.DocumentProtection.setProps(props); + } +}; + CDocument.prototype.GetDocumentLayout = function() { return this.Layout; diff --git a/word/Editor/DocumentChanges.js b/word/Editor/DocumentChanges.js index 036c2cc8e9..336fe26d8c 100644 --- a/word/Editor/DocumentChanges.js +++ b/word/Editor/DocumentChanges.js @@ -723,3 +723,306 @@ CChangesDocumentSettingsTrackRevisions.prototype.CreateReverseChange = function( { return new CChangesDocumentSettingsTrackRevisions(this.Class, this.New, this.Old, this.UserId); }; + +function CChangesDocumentProtection(Class, Old, New) { + AscDFH.CChangesBase.call(this, Class, Old, New); + if (Old && New) { + this.OldAlgorithmName = Old.algorithmName; + this.OldEdit = Old.edit; + this.OldEnforcement = Old.enforcement; + this.OldFormatting = Old.formatting; + this.OldHashValue = Old.hashValue; + this.OldSaltValue = Old.saltValue; + this.OldSpinCount = Old.spinCount; + this.OldAlgIdExt = Old.algIdExt; + this.OldAlgIdExtSource = Old.algIdExtSource; + this.OldCryptAlgorithmClass = Old.cryptAlgorithmClass; + this.OldCryptAlgorithmSid = Old.cryptAlgorithmSid; + this.OldCryptAlgorithmType = Old.cryptAlgorithmType; + this.OldCryptProvider = Old.cryptProvider; + this.OldCryptProviderType = Old.cryptProviderType; + this.OldCryptProviderTypeExt = Old.cryptProviderTypeExt; + this.OldCryptProviderTypeExtSource = Old.cryptProviderTypeExtSource; + + this.NewAlgorithmName = New.algorithmName === Old.algorithmName ? undefined : New.algorithmName; + this.NewEdit = New.edit === Old.edit ? undefined : New.edit; + this.NewEnforcement = New.enforcement === Old.enforcement ? undefined : New.enforcement; + this.NewFormatting = New.formatting === Old.formatting ? undefined : New.formatting; + this.NewHashValue = New.hashValue === Old.hashValue ? undefined : New.hashValue; + this.NewSaltValue = New.saltValue === Old.saltValue ? undefined : New.saltValue; + this.NewSpinCount = New.spinCount === Old.spinCount ? undefined : New.spinCount; + this.NewAlgIdExt = New.algIdExt === Old.algIdExt ? undefined : New.algIdExt; + this.NewAlgIdExtSource = New.algIdExtSource === Old.algIdExtSource ? undefined : New.algIdExtSource; + this.NewCryptAlgorithmClass = New.cryptAlgorithmClass === Old.cryptAlgorithmClass ? undefined : New.cryptAlgorithmClass; + this.NewCryptAlgorithmSid = New.cryptAlgorithmSid === Old.cryptAlgorithmSid ? undefined : New.cryptAlgorithmSid; + this.NewCryptAlgorithmType = New.cryptAlgorithmType === Old.cryptAlgorithmType ? undefined : New.cryptAlgorithmType; + this.NewCryptProvider = New.cryptProvider === Old.cryptProvider ? undefined : New.cryptProvider; + this.NewCryptProviderType = New.cryptProviderType === Old.cryptProviderType ? undefined : New.cryptProviderType; + this.NewCryptProviderTypeExt = New.cryptProviderTypeExt === Old.cryptProviderTypeExt ? undefined : New.cryptProviderTypeExt; + this.NewCryptProviderTypeExtSource = New.cryptProviderTypeExtSource === Old.cryptProviderTypeExtSource ? undefined : New.cryptProviderTypeExtSource; + } else { + this.OldAlgorithmName = undefined; + this.OldEdit = undefined; + this.OldEnforcement = undefined; + this.OldFormatting = undefined; + this.OldHashValue = undefined; + this.OldSaltValue = undefined; + this.OldSpinCount = undefined; + this.OldAlgIdExt = undefined; + this.OldAlgIdExtSource = undefined; + this.OldCryptAlgorithmClass = undefined; + this.OldCryptAlgorithmSid = undefined; + this.OldCryptAlgorithmType = undefined; + this.OldCryptProvider = undefined; + this.OldCryptProviderType = undefined; + this.OldCryptProviderTypeExt = undefined; + this.OldCryptProviderTypeExtSource = undefined; + + this.NewAlgorithmName = undefined; + this.NewEdit = undefined; + this.NewEnforcement = undefined; + this.NewFormatting = undefined; + this.NewHashValue = undefined; + this.NewSaltValue = undefined; + this.NewSpinCount = undefined; + this.NewAlgIdExt = undefined; + this.NewAlgIdExtSource = undefined; + this.NewCryptAlgorithmClass = undefined; + this.NewCryptAlgorithmSid = undefined; + this.NewCryptAlgorithmType = undefined; + this.NewCryptProvider = undefined; + this.NewCryptProviderType = undefined; + this.NewCryptProviderTypeExt = undefined; + this.NewCryptProviderTypeExtSource = undefined; + } +} + +CChangesDocumentProtection.prototype = Object.create(AscDFH.CChangesBase.prototype); +CChangesDocumentProtection.prototype.constructor = CChangesDocumentProtection; +CChangesDocumentProtection.prototype.Type = AscDFH.historydescription_Document_DocumentProtection; +CChangesDocumentProtection.prototype.Undo = function () { + if (!this.Class) { + return; + } + + this.Class.algorithmName = this.OldAlgorithmName; + this.Class.edit = this.OldEdit; + this.Class.enforcement = this.OldEnforcement; + this.Class.formatting = this.OldFormatting; + + this.Class.hashValue = this.OldHashValue; + this.Class.saltValue = this.OldSaltValue; + this.Class.spinCount = this.OldSpinCount; + this.Class.algIdExt = this.OldAlgIdExt; + + this.Class.algIdExtSource = this.OldAlgIdExtSource; + this.Class.cryptAlgorithmClass = this.OldCryptAlgorithmClass; + this.Class.cryptAlgorithmSid = this.OldCryptAlgorithmSid; + this.Class.cryptAlgorithmType = this.OldCryptAlgorithmType; + + this.Class.cryptProvider = this.OldCryptProvider; + this.Class.cryptProviderType = this.OldCryptProviderType; + this.Class.cryptProviderTypeExt = this.OldCryptProviderTypeExt; + this.Class.cryptProviderTypeExtSource = this.OldCryptProviderTypeExtSource; + + editor.sendEvent("asc_onChangeDocumentProtection"); +}; +CChangesDocumentProtection.prototype.Redo = function () { + if (!this.Class) { + return; + } + + this.Class.algorithmName = this.NewAlgorithmName; + this.Class.edit = this.NewEdit; + this.Class.enforcement = this.NewEnforcement; + this.Class.formatting = this.NewFormatting; + this.Class.hashValue = this.NewHashValue; + this.Class.saltValue = this.NewSaltValue; + this.Class.spinCount = this.NewSpinCount; + this.Class.formatting = this.NewFormatting; + this.Class.algIdExt = this.NewAlgIdExt; + + this.Class.algIdExtSource = this.NewAlgIdExtSource; + this.Class.cryptAlgorithmClass = this.NewCryptAlgorithmClass; + this.Class.cryptAlgorithmSid = this.NewCryptAlgorithmSid; + this.Class.cryptAlgorithmType = this.NewCryptAlgorithmType; + this.Class.cryptProvider = this.NewCryptProvider; + this.Class.cryptProviderType = this.NewCryptProviderType; + this.Class.cryptProviderTypeExt = this.NewCryptProviderTypeExt; + this.Class.cryptProviderTypeExtSource = this.NewCryptProviderTypeExtSource; + + var api = Asc.editor || editor; + if (api) { + let oDocument = api.private_GetLogicDocument(); + if (oDocument && oDocument.Settings) { + var docProtection = oDocument.Settings && oDocument.Settings.DocumentProtection; + if (!docProtection || this.Class !== docProtection) { + oDocument.Settings.DocumentProtection = this.Class; + } + } + api.sendEvent("asc_onChangeDocumentProtection"); + } +}; +CChangesDocumentProtection.prototype.WriteToBinary = function (Writer) { + if (undefined !== this.NewAlgorithmName) { + Writer.WriteBool(true); + Writer.WriteByte(this.NewAlgorithmName); + } else { + Writer.WriteBool(false); + } + if (undefined !== this.NewEdit) { + Writer.WriteBool(true); + Writer.WriteByte(this.NewEdit); + } else { + Writer.WriteBool(false); + } + if (undefined !== this.NewEnforcement) { + Writer.WriteBool(true); + Writer.WriteBool(this.NewEnforcement); + } else { + Writer.WriteBool(false); + } + if (undefined !== this.NewFormatting) { + Writer.WriteBool(true); + Writer.WriteBool(this.NewFormatting); + } else { + Writer.WriteBool(false); + } + if (undefined !== this.NewHashValue) { + Writer.WriteBool(true); + Writer.WriteString2(this.NewHashValue); + } else { + Writer.WriteBool(false); + } + if (undefined !== this.NewSaltValue) { + Writer.WriteBool(true); + Writer.WriteString2(this.NewSaltValue); + } else { + Writer.WriteBool(false); + } + if (undefined !== this.NewSpinCount) { + Writer.WriteBool(true); + Writer.WriteLong(this.NewSpinCount); + } else { + Writer.WriteBool(false); + } + if (undefined !== this.NewAlgIdExt) { + Writer.WriteBool(true); + Writer.WriteString2(this.NewAlgIdExt); + } else { + Writer.WriteBool(false); + } + if (undefined !== this.NewAlgIdExt) { + Writer.WriteBool(true); + Writer.WriteString2(this.NewAlgIdExt); + } else { + Writer.WriteBool(false); + } + if (undefined !== this.NewAlgIdExtSource) { + Writer.WriteBool(true); + Writer.WriteString2(this.NewAlgIdExtSource); + } else { + Writer.WriteBool(false); + } + + if (undefined !== this.NewCryptAlgorithmClass) { + Writer.WriteBool(true); + Writer.WriteByte(this.NewCryptAlgorithmClass); + } else { + Writer.WriteBool(false); + } + if (undefined !== this.NewCryptAlgorithmSid) { + Writer.WriteBool(true); + Writer.WriteLong(this.NewCryptAlgorithmSid); + } else { + Writer.WriteBool(false); + } + if (undefined !== this.NewCryptAlgorithmType) { + Writer.WriteBool(true); + Writer.WriteByte(this.NewCryptAlgorithmType); + } else { + Writer.WriteBool(false); + } + if (undefined !== this.NewCryptProvider) { + Writer.WriteBool(true); + Writer.WriteString2(this.NewCryptProvider); + } else { + Writer.WriteBool(false); + } + if (undefined !== this.NewCryptProviderType) { + Writer.WriteBool(true); + Writer.WriteByte(this.NewCryptProviderType); + } else { + Writer.WriteBool(false); + } + if (undefined !== this.NewCryptProviderTypeExt) { + Writer.WriteBool(true); + Writer.WriteString2(this.NewCryptProviderTypeExt); + } else { + Writer.WriteBool(false); + } + if (undefined !== this.NewCryptProviderTypeExtSource) { + Writer.WriteBool(true); + Writer.WriteString2(this.NewCryptProviderTypeExtSource); + } else { + Writer.WriteBool(false); + } +}; + +CChangesDocumentProtection.prototype.ReadFromBinary = function (Reader) { + if (Reader.GetBool()) { + this.NewAlgorithmName = Reader.GetByte(); + } + if (Reader.GetBool()) { + this.NewEdit = Reader.GetByte(); + } + if (Reader.GetBool()) { + this.NewEnforcement = Reader.GetBool(); + } + if (Reader.GetBool()) { + this.NewFormatting = Reader.GetBool(); + } + if (Reader.GetBool()) { + this.NewHashValue = Reader.GetString2(); + } + if (Reader.GetBool()) { + this.NewSaltValue = Reader.GetString2(); + } + if (Reader.GetBool()) { + this.NewSpinCount = Reader.GetLong(); + } + if (Reader.GetBool()) { + this.NewAlgIdExt = Reader.GetString2(); + } + if (Reader.GetBool()) { + this.NewAlgIdExt = Reader.GetString2(); + } + if (Reader.GetBool()) { + this.NewAlgIdExtSource = Reader.GetString2(); + } + if (Reader.GetBool()) { + this.NewCryptAlgorithmClass = Reader.GetByte(); + } + if (Reader.GetBool()) { + this.NewCryptAlgorithmSid = Reader.GetLong(); + } + if (Reader.GetBool()) { + this.NewCryptAlgorithmType = Reader.GetByte(); + } + if (Reader.GetBool()) { + this.NewCryptProvider = Reader.GetString2(); + } + if (Reader.GetBool()) { + this.NewCryptProviderType = Reader.GetByte(); + } + if (Reader.GetBool()) { + this.NewCryptProviderTypeExt = Reader.GetString2(); + } + if (Reader.GetBool()) { + this.NewCryptProviderTypeExtSource = Reader.GetString2(); + } +}; +CChangesDocumentProtection.prototype.CreateReverseChange = function () { +}; + +AscDFH.changesFactory[AscDFH.historydescription_Document_DocumentProtection] = CChangesDocumentProtection; diff --git a/word/Editor/DocumentProtection.js b/word/Editor/DocumentProtection.js index 11b20ef22a..b963f21366 100644 --- a/word/Editor/DocumentProtection.js +++ b/word/Editor/DocumentProtection.js @@ -44,14 +44,6 @@ var ECryptAlgoritmName = { SHA_512: 9, WHIRLPOOL: 10 }; - -var EDocProtect = { - Comments: 0, - Forms: 1, - None: 2, - ReadOnly: 3, - TrackedChanges: 4 -}; var ECryptAlgClass = { Custom: 0, Hash: 1 @@ -67,9 +59,11 @@ var ECryptProv = { }; function CDocProtect() { + this.Id = AscCommon.g_oIdCounter.Get_NewId(); + this.algorithmName = null; this.edit = null; - this.enforcment = null; + this.enforcement = null; this.formatting = null; this.hashValue = null; this.saltValue = null; @@ -84,13 +78,132 @@ function CDocProtect() { this.cryptProviderType = null; this.cryptProviderTypeExt = null; this.cryptProviderTypeExtSource = null; + + // Добавляем данный класс в таблицу Id (обязательно в конце конструктора) + AscCommon.g_oTableId.Add(this, this.Id); + + this.Lock = new AscCommon.CLock(); + this.lockType = AscCommon.c_oAscLockTypes.kLockTypeNone; + + this.temporaryPassword = null; } +CDocProtect.prototype.Get_Id = function () { + return this.Id; +}; CDocProtect.prototype.isOnlyView = function () { - return this.edit === EDocProtect.ReadOnly; + return this.edit === Asc.c_oAscEDocProtect.ReadOnly; +}; +CDocProtect.prototype.getEnforcement = function () { + return this.enforcement; +}; +CDocProtect.prototype.getRestrictionType = function () { + var res = null; + switch (this.edit) { + case Asc.c_oAscEDocProtect.Comments: + res = Asc.c_oAscRestrictionType.OnlyComments; + break; + case Asc.c_oAscEDocProtect.Forms: + res = Asc.c_oAscRestrictionType.OnlyForms; + break; + case Asc.c_oAscEDocProtect.ReadOnly: + res = Asc.c_oAscRestrictionType.View; + break; + case Asc.c_oAscEDocProtect.TrackedChanges: + //asc_SetLocalTrackRevisions + //asc_SetGlobalTrackRevisions + res = Asc.c_oAscRestrictionType.OnlySignatures; + break; + } + return res; +}; +CDocProtect.prototype.generateHashParams = function () { + var params = AscCommon.generateHashParams(); + + this.saltValue = params.saltValue; + this.spinCount = params.spinCount; + //this.algorithmName = params.algorithmName; +}; +CDocProtect.prototype.generateHashParams = function () { + var params = AscCommon.generateHashParams(); + + this.saltValue = params.saltValue; + this.spinCount = params.spinCount; + //this.algorithmName = params.algorithmName; }; -CDocProtect.prototype.getEnforcment = function () { - return this.enforcment; +CDocProtect.prototype.getAlgorithmNameForCheck = function () { + if (this.algorithmName) { + return AscCommon.fromModelAlgorithmName(this.algorithmName); + } else if (this.cryptAlgorithmSid) { + return AscCommon.fromModelCryptAlgorithmSid(this.cryptAlgorithmSid); + } + return null; }; +CDocProtect.prototype.isPassword = function () { + return this.algorithmName != null || this.cryptAlgorithmSid != null; +}; +CDocProtect.prototype.setProps = function (oProps) { + History.Add(new CChangesDocumentProtection(this, this, oProps)); + this.setFromInterface(oProps); +}; +CDocProtect.prototype.setFromInterface = function (oProps) { + this.edit = oProps.edit; + this.saltValue = oProps.saltValue; + this.spinCount = oProps.spinCount; + this.cryptAlgorithmSid = oProps.cryptAlgorithmSid; + this.hashValue = oProps.hashValue; + + this.enforcement = oProps.enforcement; +}; +CDocProtect.prototype.Refresh_RecalcData = function () { +}; +CDocProtect.prototype.Copy = function () { + return AscFormat.ExecuteNoHistory(function () { + var oDocProtect = new CDocProtect(); + oDocProtect.algorithmName = this.algorithmName; + oDocProtect.edit = this.edit; + oDocProtect.enforcement = this.enforcement; + oDocProtect.formatting = this.formatting; + oDocProtect.hashValue = this.hashValue; + oDocProtect.saltValue = this.saltValue; + oDocProtect.spinCount = this.spinCount; + oDocProtect.algIdExt = this.algIdExt; + oDocProtect.algIdExtSource = this.algIdExtSource; + oDocProtect.cryptAlgorithmClass = this.cryptAlgorithmClass; + oDocProtect.cryptAlgorithmSid = this.cryptAlgorithmSid; + oDocProtect.cryptAlgorithmType = this.cryptAlgorithmType; + oDocProtect.cryptProvider = this.cryptProvider; + oDocProtect.cryptProviderType = this.cryptProviderType; + oDocProtect.cryptProviderTypeExt = this.cryptProviderTypeExt; + oDocProtect.cryptProviderTypeExtSource = this.cryptProviderTypeExtSource; + return oDocProtect; + }, this, []); +}; +/*CDocProtect.prototype.Write_ToBinary2 = function(Writer) +{ + Writer.WriteLong(AscDFH.historyitem_type_DocumentProtection); + Writer.WriteString2("" + this.Id); +}; +CDocProtect.prototype.Read_FromBinary2 = function(Reader) +{ + this.Id = Reader.GetString2(); +};*/ +CDocProtect.prototype.asc_getIsPassword = function() +{ + return this.enforcement ? this.isPassword() : null +}; +CDocProtect.prototype.asc_getEditType = function() +{ + return this.edit; +}; +CDocProtect.prototype.asc_setPassword = function(val) +{ + this.temporaryPassword = val; +}; +CDocProtect.prototype.asc_setEditType = function(val) +{ + this.edit = val; +}; + function CWriteProtection() { this.algorithmName = null; @@ -109,3 +222,10 @@ function CWriteProtection() { this.cryptProviderTypeExt = null; this.cryptProviderTypeExtSource = null; } + +window['AscCommonWord'].CDocProtect = CDocProtect; +prot = CDocProtect.prototype; +prot["asc_getIsPassword"] = prot.asc_getIsPassword; +prot["asc_getEditType"] = prot.asc_getEditType; +prot["asc_setEditType"] = prot.asc_setEditType; +prot["asc_setPassword"] = prot.asc_setPassword; diff --git a/word/Editor/DocumentSettings.js b/word/Editor/DocumentSettings.js index 8493445d3b..3922beccde 100644 --- a/word/Editor/DocumentSettings.js +++ b/word/Editor/DocumentSettings.js @@ -46,7 +46,7 @@ this.SdtSettings = new CSdtGlobalSettings(); this.SpecialFormsSettings = new CSpecialFormsGlobalSettings(); this.WriteProtection = undefined; - this.DocumentProtection = undefined; + this.DocumentProtection = new AscCommonWord.CDocProtect(); this.ListSeparator = undefined; this.DecimalSymbol = undefined; diff --git a/word/Editor/Serialize2.js b/word/Editor/Serialize2.js index b461549d39..7c1aa2ac56 100644 --- a/word/Editor/Serialize2.js +++ b/word/Editor/Serialize2.js @@ -722,7 +722,7 @@ var c_oSer_SettingsType = { var c_oDocProtect = { AlgorithmName: 0, Edit: 1, - Enforcment: 2, + Enforcement: 2, Formatting: 3, HashValue: 4, SaltValue: 5, @@ -7250,16 +7250,16 @@ function BinarySettingsTableWriter(memory, doc, saveParams) oThis.memory.WriteByte(oDocProtect.algorithmName); }); } - if (oDocProtect.edit) + if (null !== oDocProtect.edit) { this.bs.WriteItem(c_oDocProtect.Edit, function () { oThis.memory.WriteByte(oDocProtect.edit); }); } - if (null !== oDocProtect.enforcment) + if (null !== oDocProtect.enforcement) { - this.bs.WriteItem(c_oDocProtect.Enforcment, function () { - oThis.memory.WriteBool(oDocProtect.enforcment); + this.bs.WriteItem(c_oDocProtect.Enforcement, function () { + oThis.memory.WriteBool(oDocProtect.enforcement); }); } if (null !== oDocProtect.formatting) @@ -8380,7 +8380,12 @@ function BinaryFileReader(doc, openParams) var docProtection = this.Document.Settings && this.Document.Settings.DocumentProtection; if (docProtection) { - if (docProtection.isOnlyView() && false !== docProtection.getEnforcment()) { + //this.Document.applyProtection() + var restrictionType = docProtection.getRestrictionType(); + if (/*docProtection.isOnlyView() && false !== docProtection.getEnforcement()*/restrictionType !== null) { + api && api.asc_addRestriction(restrictionType); + } else if (false !== docProtection.getEnforcement() ) { + //TODO ? api && api.asc_addRestriction(Asc.c_oAscRestrictionType.View); } } @@ -16292,7 +16297,7 @@ function Binary_SettingsTableReader(doc, oReadResult, stream) res = this.bcr.Read1(length, function(t, l){ return oThis.ReadDocProtect(t,l,oDocProtect); }); - //Settings.DocumentProtection = oDocProtect; + Settings.DocumentProtection = oDocProtect; } else if ( c_oSer_SettingsType.WriteProtection === type ) { @@ -16820,9 +16825,9 @@ function Binary_SettingsTableReader(doc, oReadResult, stream) { pDocProtect.edit = this.stream.GetUChar(); } - else if (c_oDocProtect.Enforcment == type) + else if (c_oDocProtect.Enforcement == type) { - pDocProtect.enforcment = this.stream.GetUChar() != 0; + pDocProtect.enforcement = this.stream.GetUChar() != 0; } else if (c_oDocProtect.Formatting == type) { diff --git a/word/api.js b/word/api.js index 379923ad4b..8f7674f7be 100644 --- a/word/api.js +++ b/word/api.js @@ -1754,6 +1754,10 @@ background-repeat: no-repeat;\ { editor.sendEvent("asc_onLockCore", true); } + else if(Class instanceof AscCommonWord.CDocProtect) + { + editor.sendEvent("asc_onLockDocumentProtection", true); + } // Теперь обновлять состояние необходимо, чтобы обновить локи в режиме рецензирования. t.WordControl.m_oLogicDocument.UpdateInterface(undefined, true); } @@ -1863,6 +1867,17 @@ background-repeat: no-repeat;\ editor.sendEvent("asc_onLockCore", false); } } + else if(Class instanceof AscCommonWord.CDocProtect) + { + if (NewType !== locktype_Mine && NewType !== locktype_None) + { + editor.sendEvent("asc_onLockDocumentProtection", true); + } + else + { + editor.sendEvent("asc_onLockDocumentProtection", false); + } + } } } else @@ -12828,6 +12843,125 @@ background-repeat: no-repeat;\ return oDocument.PutImageToSelection(sImageSrc, nWidth, nHeight); }; + asc_docs_api.prototype.asc_getDocumentProtection = function () { + let oDocument = this.private_GetLogicDocument(); + if (!oDocument) { + return; + } + + var docProtection = oDocument.Settings && oDocument.Settings.DocumentProtection; + if (docProtection) { + return docProtection.Copy(); + } + }; + + asc_docs_api.prototype.asc_setDocumentProtection = function (props) { + //props -> CDocProtect + + // Проверка глобального лока + if (AscCommon.CollaborativeEditing.Get_GlobalLock()) { + return; + } + + let oDocument = this.private_GetLogicDocument(); + if (!oDocument) { + return; + } + var t = this; + + var calculatedHashValue; + var callback = function (res) { + t.sync_EndAction(Asc.c_oAscAsyncActionType.BlockInteraction); + + if (res) { + if(false === oDocument.Document_Is_SelectionLocked(AscCommon.changestype_DocumentProtection, null, null, true)) + { + oDocument.StartAction(AscDFH.historydescription_Document_DocumentProtection); + + props.saltValue = salt; + props.spinCount = spinCount; + props.cryptAlgorithmSid = alg; + props.hashValue = calculatedHashValue; + props.enforcement = props.edit !== Asc.c_oAscEDocProtect.None; + + oDocument.SetProtection(props); + oDocument.UpdateInterface(); + oDocument.FinalizeAction(); + t.sendEvent("asc_onChangeDocumentProtection"); + } + } else { + t.sendEvent("asc_onError", c_oAscError.ID.PasswordIsNotCorrect, c_oAscError.Level.NoCritical); + } + }; + + var password = props.temporaryPassword; + props.temporaryPassword = null; + var documentProtection = oDocument.Settings.DocumentProtection; + var salt, alg, spinCount; + if (password !== "" && password != null) { + if (documentProtection) { + salt = documentProtection.saltValue; + spinCount = documentProtection.spinCount; + alg = documentProtection.cryptAlgorithmSid; + } + + if (!salt || !spinCount) { + var params = AscCommon.generateHashParams(); + salt = params.saltValue; + spinCount = params.spinCount; + } + + if (!alg) { + alg = AscCommon.c_oSerCryptAlgorithmSid.SHA_512; + } + } + + var checkPassword = function (hash, doNotCheckPassword) { + if (doNotCheckPassword) { + callback(true); + } else { + if (props != null && props.edit != null && props.edit !== Asc.c_oAscEDocProtect.None) { + //устанавливаем защиту + calculatedHashValue = hash && hash[0] ? hash[0] : null; + callback(true); + } else { + //пробуем снять защиту + if (documentProtection && hash && (hash[0] === documentProtection.hashValue || hash[1] === documentProtection.hashValue)) { + callback(true); + } else { + //неверный пароль + t.sendEvent("asc_onError", c_oAscError.ID.PasswordIsNotCorrect, c_oAscError.Level.NoCritical); + t.sendEvent("asc_onChangeDocumentProtection"); + t.sync_EndAction(Asc.c_oAscAsyncActionType.BlockInteraction); + } + } + } + }; + + this.sync_StartAction(Asc.c_oAscAsyncActionType.BlockInteraction); + if (password != null) { + if (password === "") { + checkPassword([""]); + } else { + //перед тем, как сгенерировать хэш, мс предварительно преобразовывает пароль + //в мс подходит как преобразованные пароль, так и не преобразованный + //т.е. если сгенерировать вручную хэш из непреобразованного пароля и положить в xml, то документ можно будет разблокировать по первоначальному паролю + var hashPassword = AscCommon.prepareWordPassword(password); + var hashArr = []; + if (hashPassword) { + hashArr.push({password: hashPassword, salt: salt, spinCount: spinCount, alg: AscCommon.fromModelCryptAlgorithmSid(alg)}); + } + hashArr.push({password: password, salt: salt, spinCount: spinCount, alg: AscCommon.fromModelCryptAlgorithmSid(alg)}); + AscCommon.calculateProtectHash(hashArr, checkPassword); + } + } else { + checkPassword(null, true); + } + + return true; + }; + + //-------------------------------------------------------------export--------------------------------------------------- window['Asc'] = window['Asc'] || {}; CAscSection.prototype['get_PageWidth'] = CAscSection.prototype.get_PageWidth; @@ -13588,6 +13722,8 @@ background-repeat: no-repeat;\ asc_docs_api.prototype["asc_editPointsGeometry"] = asc_docs_api.prototype.asc_editPointsGeometry; asc_docs_api.prototype["asc_getTableStylesPreviews"] = asc_docs_api.prototype.asc_getTableStylesPreviews; asc_docs_api.prototype["asc_generateTableStylesPreviews"] = asc_docs_api.prototype.asc_generateTableStylesPreviews; + asc_docs_api.prototype["asc_getDocumentProtection"] = asc_docs_api.prototype.asc_getDocumentProtection; + asc_docs_api.prototype["asc_setDocumentProtection"] = asc_docs_api.prototype.asc_setDocumentProtection; CDocInfoProp.prototype['get_PageCount'] = CDocInfoProp.prototype.get_PageCount; CDocInfoProp.prototype['put_PageCount'] = CDocInfoProp.prototype.put_PageCount; diff --git a/word/apiDefines.js b/word/apiDefines.js index f37dce0623..c1edd43989 100644 --- a/word/apiDefines.js +++ b/word/apiDefines.js @@ -876,6 +876,14 @@ c_oAscDateTimeFormat[lcid_enUS] = [ "HH:mm:ss" ]; +var c_oAscEDocProtect = { + Comments: 0, + Forms: 1, + None: 2, + ReadOnly: 3, + TrackedChanges: 4 +}; + //------------------------------------------------------------export--------------------------------------------------- var prot; window['Asc'] = window['Asc'] || {}; @@ -1057,3 +1065,10 @@ prot['Content'] = prot.Content; prot['Window'] = prot.Window; window['Asc']['c_oAscDateTimeFormat'] = window['Asc'].c_oAscDateTimeFormat = c_oAscDateTimeFormat; + +prot = window['Asc']['c_oAscEDocProtect'] = window['Asc'].c_oAscEDocProtect = c_oAscEDocProtect; +prot['Comments'] = prot.Comments; +prot['Forms'] = prot.Forms; +prot['None'] = prot.None; +prot['ReadOnly'] = prot.ReadOnly; +prot['TrackedChanges'] = prot.TrackedChanges;