From bba56501036887816ff45a4c6a712b7d57cbfdf7 Mon Sep 17 00:00:00 2001 From: igor Date: Thu, 24 Aug 2023 14:52:58 +0600 Subject: [PATCH] =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D1=8C=D1=82=D1=80=20=D0=B2?= =?UTF-8?q?=20showRecord=20=D0=BA=D0=BD=D0=BE=D0=BF=D0=BA=D0=B0=20"..."?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- metadata/dbms/showrecord.js | 30 +- metadata/include/otp/FixedByteNotation.php | 276 +++++++++++++++++++ metadata/include/otp/GoogleAuthenticator.php | 88 ++++++ 3 files changed, 381 insertions(+), 13 deletions(-) create mode 100644 metadata/include/otp/FixedByteNotation.php create mode 100644 metadata/include/otp/GoogleAuthenticator.php diff --git a/metadata/dbms/showrecord.js b/metadata/dbms/showrecord.js index 22f8cd7..2026153 100644 --- a/metadata/dbms/showrecord.js +++ b/metadata/dbms/showrecord.js @@ -413,28 +413,35 @@ class SRec } //we pass the id to the object filter column_n - the name of the filter - setFilterObject(TypeName, column_n, id, filter) + setFilterObject(TypeName, column_n, id, nodeFilter) { let node=findFirstNodeOnAttribute(this.nodeMetadata,'column','n',column_n); if(node!==null) { let name=node.getAttribute("FieldCaption"); + getCdata(node).nodeValue=id; //we request data from the server to fill in the comments on the record id let prop=document.getElementById('filter_'+this.uid+'_'+column_n); if(prop!==null) prop.value = id; //Request a comment on the record id from the server let xml = ''; - if(filter!=''){ + if(nodeFilter!=null){ //Настройка для последующего вызова - xml=''+filter+''; + xml=''+getXMLNodeSerialisation(nodeFilter)+''; applyNodeToNode(CreateXMLDOC(xml).documentElement, node, "n"); - //Настройка для фильтрации списка - xml = '' + - '' + - '' + filter + '' + - ''; + if(node.getAttribute("selector")=="combo") { + xml = '' + + '' + + '' + getXMLNodeSerialisation(nodeFilter) + '' + + ''; + }else{ + xml = '' + + '' + + '' + + ''; + } }else{ xml = '' + '' + @@ -1631,14 +1638,10 @@ class SRec let filter=""; let nodeType=findFirstNode(this.nodeMetadata, "type"); let nodeFilter=findNodeOnPath(nodeType,"objects-list/filter"); - if (nodeFilter!=null) - { - filter=getXMLNodeSerialisation(nodeFilter) - } //Send the id of the selected record to the parent of the selected record and close the window //alert2(trt('Alert'),"id="+id+" f_PropName="+this.f_PropName+" f_TypeName="+this.f_TypeName); - this.opener.setFilterObject(this.f_TypeName, this.f_PropName, id, filter); + this.opener.setFilterObject(this.f_TypeName, this.f_PropName, id, nodeFilter); this.win.Close(); }else{ let erec = new EdtRec(""); @@ -1652,6 +1655,7 @@ class SRec }else if(this.f_State=="2") //Multiple choice (on the records of ticking TODO is not implemented) { + alert2(trt('Alert'), 'TODO'); } } diff --git a/metadata/include/otp/FixedByteNotation.php b/metadata/include/otp/FixedByteNotation.php new file mode 100644 index 0000000..97d22f7 --- /dev/null +++ b/metadata/include/otp/FixedByteNotation.php @@ -0,0 +1,276 @@ += ($radix <<= 1) && $bitsPerCharacter < 8) { + $bitsPerCharacter++; + } + + $radix >>= 1; + + } elseif ($bitsPerCharacter > 8) { + // $bitsPerCharacter must not be greater than 8 + $bitsPerCharacter = 8; + $radix = 256; + + } else { + $radix = 1 << $bitsPerCharacter; + } + + $this->_chars = $chars; + $this->_bitsPerCharacter = $bitsPerCharacter; + $this->_radix = $radix; + $this->_rightPadFinalBits = $rightPadFinalBits; + $this->_padFinalGroup = $padFinalGroup; + $this->_padCharacter = $padCharacter[0]; + } + + /** + * Encode a string + * + * @param string $rawString Binary data to encode + * @return string + */ + public function encode($rawString) + { + // Unpack string into an array of bytes + $bytes = unpack('C*', $rawString); + $byteCount = count($bytes); + + $encodedString = ''; + $byte = array_shift($bytes); + $bitsRead = 0; + + $chars = $this->_chars; + $bitsPerCharacter = $this->_bitsPerCharacter; + $rightPadFinalBits = $this->_rightPadFinalBits; + $padFinalGroup = $this->_padFinalGroup; + $padCharacter = $this->_padCharacter; + + // Generate encoded output; + // each loop produces one encoded character + for ($c = 0; $c < $byteCount * 8 / $bitsPerCharacter; $c++) { + + // Get the bits needed for this encoded character + if ($bitsRead + $bitsPerCharacter > 8) { + // Not enough bits remain in this byte for the current + // character + // Save the remaining bits before getting the next byte + $oldBitCount = 8 - $bitsRead; + $oldBits = $byte ^ ($byte >> $oldBitCount << $oldBitCount); + $newBitCount = $bitsPerCharacter - $oldBitCount; + + if (!$bytes) { + // Last bits; match final character and exit loop + if ($rightPadFinalBits) $oldBits <<= $newBitCount; + $encodedString .= $chars[$oldBits]; + + if ($padFinalGroup) { + // Array of the lowest common multiples of + // $bitsPerCharacter and 8, divided by 8 + $lcmMap = array(1 => 1, 2 => 1, 3 => 3, 4 => 1, + 5 => 5, 6 => 3, 7 => 7, 8 => 1); + $bytesPerGroup = $lcmMap[$bitsPerCharacter]; + $pads = $bytesPerGroup * 8 / $bitsPerCharacter + - ceil((strlen($rawString) % $bytesPerGroup) + * 8 / $bitsPerCharacter); + $encodedString .= str_repeat($padCharacter[0], $pads); + } + + break; + } + + // Get next byte + $byte = array_shift($bytes); + $bitsRead = 0; + + } else { + $oldBitCount = 0; + $newBitCount = $bitsPerCharacter; + } + + // Read only the needed bits from this byte + $bits = $byte >> 8 - ($bitsRead + ($newBitCount)); + $bits ^= $bits >> $newBitCount << $newBitCount; + $bitsRead += $newBitCount; + + if ($oldBitCount) { + // Bits come from seperate bytes, add $oldBits to $bits + $bits = ($oldBits << $newBitCount) | $bits; + } + + $encodedString .= $chars[$bits]; + } + + return $encodedString; + } + + /** + * Decode a string + * + * @param string $encodedString Data to decode + * @param boolean $caseSensitive + * @param boolean $strict Returns NULL if $encodedString contains + * an undecodable character + * @return string|NULL + */ + public function decode($encodedString, $caseSensitive = TRUE, + $strict = FALSE) + { + if (!$encodedString || !is_string($encodedString)) { + // Empty string, nothing to decode + return ''; + } + + $chars = $this->_chars; + $bitsPerCharacter = $this->_bitsPerCharacter; + $radix = $this->_radix; + $rightPadFinalBits = $this->_rightPadFinalBits; + $padFinalGroup = $this->_padFinalGroup; + $padCharacter = $this->_padCharacter; + + // Get index of encoded characters + if ($this->_charmap) { + $charmap = $this->_charmap; + + } else { + $charmap = array(); + + for ($i = 0; $i < $radix; $i++) { + $charmap[$chars[$i]] = $i; + } + + $this->_charmap = $charmap; + } + + // The last encoded character is $encodedString[$lastNotatedIndex] + $lastNotatedIndex = strlen($encodedString) - 1; + + // Remove trailing padding characters + while ($encodedString[$lastNotatedIndex] == $padCharacter[0]) { + $encodedString = substr($encodedString, 0, $lastNotatedIndex); + $lastNotatedIndex--; + } + + $rawString = ''; + $byte = 0; + $bitsWritten = 0; + + // Convert each encoded character to a series of unencoded bits + for ($c = 0; $c <= $lastNotatedIndex; $c++) { + + if (!isset($charmap[$encodedString[$c]]) && !$caseSensitive) { + // Encoded character was not found; try other case + if (isset($charmap[$cUpper + = strtoupper($encodedString[$c])])) { + $charmap[$encodedString[$c]] = $charmap[$cUpper]; + + } elseif (isset($charmap[$cLower + = strtolower($encodedString[$c])])) { + $charmap[$encodedString[$c]] = $charmap[$cLower]; + } + } + + if (isset($charmap[$encodedString[$c]])) { + $bitsNeeded = 8 - $bitsWritten; + $unusedBitCount = $bitsPerCharacter - $bitsNeeded; + + // Get the new bits ready + if ($bitsNeeded > $bitsPerCharacter) { + // New bits aren't enough to complete a byte; shift them + // left into position + $newBits = $charmap[$encodedString[$c]] << $bitsNeeded + - $bitsPerCharacter; + $bitsWritten += $bitsPerCharacter; + + } elseif ($c != $lastNotatedIndex || $rightPadFinalBits) { + // Zero or more too many bits to complete a byte; + // shift right + $newBits = $charmap[$encodedString[$c]] >> $unusedBitCount; + $bitsWritten = 8; //$bitsWritten += $bitsNeeded; + + } else { + // Final bits don't need to be shifted + $newBits = $charmap[$encodedString[$c]]; + $bitsWritten = 8; + } + + $byte |= $newBits; + + if ($bitsWritten == 8 || $c == $lastNotatedIndex) { + // Byte is ready to be written + $rawString .= pack('C', $byte); + + if ($c != $lastNotatedIndex) { + // Start the next byte + $bitsWritten = $unusedBitCount; + $byte = ($charmap[$encodedString[$c]] + ^ ($newBits << $unusedBitCount)) << 8 - $bitsWritten; + } + } + + } elseif ($strict) { + // Unable to decode character; abort + return NULL; + } + } + + return $rawString; + } +} diff --git a/metadata/include/otp/GoogleAuthenticator.php b/metadata/include/otp/GoogleAuthenticator.php new file mode 100644 index 0000000..344c034 --- /dev/null +++ b/metadata/include/otp/GoogleAuthenticator.php @@ -0,0 +1,88 @@ +getCode($secret,$time + $i) == $code) { + return true; + } + } + + return false; + + } + + public function getCode($secret,$time = null) { + + if (!$time) { + $time = floor(time() / 30); + } + $base32 = new FixedBitNotation(5, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', TRUE, TRUE); + $secret = $base32->decode($secret); + + $time = pack("N", $time); + $time = str_pad($time,8, chr(0), STR_PAD_LEFT); + + $hash = hash_hmac('sha1',$time,$secret,true); + $offset = ord(substr($hash,-1)); + $offset = $offset & 0xF; + + $truncatedHash = self::hashToInt($hash, $offset) & 0x7FFFFFFF; + $pinValue = str_pad($truncatedHash % self::$PIN_MODULO,6,"0",STR_PAD_LEFT);; + return $pinValue; + } + + protected function hashToInt($bytes, $start) { + $input = substr($bytes, $start, strlen($bytes) - $start); + $val2 = unpack("N",substr($input,0,4)); + return $val2[1]; + } + + public function getUrl($user, $hostname, $secret) { + $url = sprintf("otpauth://totp/%s@%s?secret=%s", $user, $hostname, $secret); + $encoder = "https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl="; + $encoderURL = sprintf( "%sotpauth://totp/%s@%s&secret=%s",$encoder, $user, $hostname, $secret); + + return $encoderURL; + + } + + public function generateSecret() { + $secret = ""; + for($i = 1; $i<= self::$SECRET_LENGTH;$i++) { + $c = rand(0,255); + $secret .= pack("c",$c); + } + $base32 = new FixedBitNotation(5, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', TRUE, TRUE); + return $base32->encode($secret); + + + } + +} +