4
1
mirror of https://github.com/QuasarApp/Heart.git synced 2025-05-10 16:39:41 +00:00

Merge pull request from QuasarApp/task_313_CheatCard

Improvements from the CheatCard's next release branch.
This commit is contained in:
Andrei Yankovich 2022-11-05 22:54:48 +03:00 committed by GitHub
commit 9a3e09bec7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
82 changed files with 1234 additions and 2972 deletions

@ -45,7 +45,15 @@ endif()
# Use only for android debug builds with debugging from usb.
option(HEART_STATIC_SSL "This option enable or disabled static link ssl libraryes" OFF)
option(HEART_SSL "This option enable or disabled ssl functions of nodes" ON)
option(CMAKE_SHARE "This option enable or disabled ssl functions of nodes" OFF)
option(BUILD_SHARED_LIBS "Enable or disable shared libraryes" OFF)
if (WIN32)
option(HEART_SSL "This option enable or disabled ssl functions of nodes" OFF)
else()
option(HEART_SSL "This option enable or disabled ssl functions of nodes" ON)
endif()
if (HEART_DB_CACHE)
add_definitions(-DHEART_DB_CACHE)

@ -1,878 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="218.722mm" height="114.653mm"
viewBox="0 0 620 325"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.2" baseProfile="tiny">
<title>Qt SVG Document</title>
<desc>Generated with Qt</desc>
<defs>
<linearGradient gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1" id="gradient1">
<stop offset="0" stop-color="#ebfdff" stop-opacity="1" />
<stop offset="1" stop-color="#bfe4e8" stop-opacity="1" />
</linearGradient>
<linearGradient gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1" id="gradient2">
<stop offset="0" stop-color="#ebfdff" stop-opacity="1" />
<stop offset="1" stop-color="#bfe4e8" stop-opacity="1" />
</linearGradient>
<linearGradient gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1" id="gradient3">
<stop offset="0" stop-color="#ebfdff" stop-opacity="1" />
<stop offset="1" stop-color="#bfe4e8" stop-opacity="1" />
</linearGradient>
<linearGradient gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1" id="gradient4">
<stop offset="0" stop-color="#ebfdff" stop-opacity="1" />
<stop offset="1" stop-color="#bfe4e8" stop-opacity="1" />
</linearGradient>
<linearGradient gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1" id="gradient5">
<stop offset="0" stop-color="#ebfdff" stop-opacity="1" />
<stop offset="1" stop-color="#bfe4e8" stop-opacity="1" />
</linearGradient>
<linearGradient gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1" id="gradient6">
<stop offset="0" stop-color="#ebfdff" stop-opacity="1" />
<stop offset="1" stop-color="#bfe4e8" stop-opacity="1" />
</linearGradient>
<linearGradient gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1" id="gradient7">
<stop offset="0" stop-color="#ffecd4" stop-opacity="1" />
<stop offset="1" stop-color="#e8cdaa" stop-opacity="1" />
</linearGradient>
<linearGradient gradientUnits="objectBoundingBox" x1="0" y1="0" x2="0" y2="1" id="gradient8">
<stop offset="0" stop-color="#f9eaff" stop-opacity="1" />
<stop offset="1" stop-color="#cec1d3" stop-opacity="1" />
</linearGradient>
</defs>
<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" >
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,-53.1538,-112.277)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="#ffffff" fill-opacity="1" stroke="none" transform="matrix(0.969231,0,0,0.969231,-53.1538,-112.277)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<rect x="60" y="121" width="620" height="325"/>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,-53.1538,-112.277)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,513.846,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,513.846,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,421.769,100.954)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="url(#gradient1)" stroke="#5d979d" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,421.769,100.954)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<rect x="0" y="0" width="190" height="200"/>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,421.769,100.954)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,421.769,100.954)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,469.027,298.677)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,469.027,298.677)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,469.027,298.677)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="15" font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>Storage Location</text>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,469.027,298.677)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,469.027,298.677)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,469.027,298.677)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,469.027,298.677)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,460.538,144.569)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,460.538,144.569)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,441.154,115.492)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="url(#gradient2)" stroke="#5d979d" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,441.154,115.492)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<path vector-effect="none" fill-rule="evenodd" d="M0,0 L24,0 L40,16 L40,60 L0,60 L0,0"/>
<polyline fill="none" vector-effect="none" points="24,0 24,16 " />
<polyline fill="none" vector-effect="none" points="24,16 40,16 " />
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,441.154,115.492)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,441.154,115.492)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,436.391,177.523)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,436.391,177.523)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,436.391,177.523)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="15" font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>KeyData</text>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,436.391,177.523)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,436.391,177.523)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,436.391,177.523)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,436.391,177.523)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,562.308,144.569)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,562.308,144.569)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,542.923,115.492)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="url(#gradient3)" stroke="#5d979d" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,542.923,115.492)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<path vector-effect="none" fill-rule="evenodd" d="M0,0 L24,0 L40,16 L40,60 L0,60 L0,0"/>
<polyline fill="none" vector-effect="none" points="24,0 24,16 " />
<polyline fill="none" vector-effect="none" points="24,16 40,16 " />
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,542.923,115.492)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,542.923,115.492)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,177.523)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,177.523)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,177.523)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="15" font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>KeyData2</text>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,177.523)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,177.523)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,177.523)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,177.523)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,460.538,231.8)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,460.538,231.8)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,441.154,202.723)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="url(#gradient4)" stroke="#5d979d" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,441.154,202.723)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<path vector-effect="none" fill-rule="evenodd" d="M0,0 L24,0 L40,16 L40,60 L0,60 L0,0"/>
<polyline fill="none" vector-effect="none" points="24,0 24,16 " />
<polyline fill="none" vector-effect="none" points="24,16 40,16 " />
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,441.154,202.723)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,441.154,202.723)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,433.385,264.754)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,433.385,264.754)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,433.385,264.754)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="15" font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>KeyData3</text>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,433.385,264.754)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,433.385,264.754)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,433.385,264.754)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,433.385,264.754)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,562.308,231.8)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,562.308,231.8)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,542.923,202.723)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="url(#gradient5)" stroke="#5d979d" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,542.923,202.723)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<path vector-effect="none" fill-rule="evenodd" d="M0,0 L24,0 L40,16 L40,60 L0,60 L0,0"/>
<polyline fill="none" vector-effect="none" points="24,0 24,16 " />
<polyline fill="none" vector-effect="none" points="24,16 40,16 " />
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,542.923,202.723)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,542.923,202.723)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,264.754)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,264.754)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,264.754)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="15" font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>KeyData3</text>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,264.754)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,264.754)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,264.754)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,535.154,264.754)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,168.8)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,168.8)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,5,42.8)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="url(#gradient6)" stroke="#5d979d" stroke-opacity="1" stroke-width="2" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,5,42.8)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<path vector-effect="none" fill-rule="evenodd" d="M0,0 L52.5,-39 L402.5,-39 L402.5,221 L350,260 L0,260 L0,0"/>
<polyline fill="none" vector-effect="none" points="0,0 350,0 " />
<polyline fill="none" vector-effect="none" points="350,0 402.5,-39 " />
<polyline fill="none" vector-effect="none" points="350,0 350,260 " />
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,5,42.8)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,5,42.8)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,115.5,46.6769)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,115.5,46.6769)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,115.5,46.6769)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="19.3594" y="15" font-family="Ubuntu" font-size="11" font-weight="700" font-style="normal"
>Node (Server or</text>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="43.2656" y="28" font-family="Ubuntu" font-size="11" font-weight="700" font-style="normal"
>Client)</text>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,115.5,46.6769)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,115.5,46.6769)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,115.5,46.6769)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,115.5,46.6769)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,178.492)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,178.492)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,178.492)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="url(#gradient7)" stroke="#ac7e42" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,178.492)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<rect x="-155" y="-95" width="310" height="190"/>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,178.492)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,132.938)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#ac7e42" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,132.938)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<polyline fill="none" vector-effect="none" points="-155,4 155,4 " />
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,132.938)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,140.692)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#ac7e42" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,140.692)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<polyline fill="none" vector-effect="none" points="-155,4 155,4 " />
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,140.692)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,168.149,90.2923)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,168.149,90.2923)"
font-family="Ubuntu" font-size="9" font-weight="400" font-style="normal"
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="0" y="9" font-family="Ubuntu" font-size="9" font-weight="400" font-style="normal"
>QH</text>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,168.149,90.2923)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,142.964,100.954)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,142.964,100.954)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,142.964,100.954)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="15" font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>KeyStorage</text>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,142.964,100.954)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,142.964,100.954)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,142.964,100.954)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,142.964,100.954)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,132.643,122.277)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,132.643,122.277)"
font-family="Ubuntu" font-size="9" font-weight="400" font-style="normal"
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="0" y="9" font-family="Ubuntu" font-size="9" font-weight="400" font-style="normal"
>(from AbstractSpace)</text>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,132.643,122.277)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="url(#gradient8)" stroke="#7e6687" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<rect x="-140" y="-50" width="280" height="100"/>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,174.615,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,118.029,153.292)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,118.029,153.292)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,118.029,153.292)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="15" font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>ReadAllData methods</text>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,118.029,153.292)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,118.029,153.292)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,118.029,153.292)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,118.029,153.292)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,132.643,174.615)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,132.643,174.615)"
font-family="Ubuntu" font-size="9" font-weight="400" font-style="normal"
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="0" y="9" font-family="Ubuntu" font-size="9" font-weight="400" font-style="normal"
>(from AbstractSpace)</text>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,132.643,174.615)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,310.308,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,310.308,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,310.308,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,310.308,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,310.308,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-dasharray="4,4" stroke-dashoffset="0" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,310.308,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<path vector-effect="none" fill-rule="evenodd" d="M10.3923,0 L104.608,0"/>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,310.308,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,421.769,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,421.769,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,421.769,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<path vector-effect="none" fill-rule="evenodd" d="M-10.3923,-6 L0,0 L-10.3923,6"/>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,421.769,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(-0.969231,8.70301e-11,-8.70301e-11,-0.969231,310.308,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(-0.969231,8.70301e-11,-8.70301e-11,-0.969231,310.308,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(-0.969231,8.70301e-11,-8.70301e-11,-0.969231,310.308,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<path vector-effect="none" fill-rule="evenodd" d="M-10.3923,-6 L0,0 L-10.3923,6"/>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(-0.969231,8.70301e-11,-8.70301e-11,-0.969231,310.308,197.877)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,42.8,178.492)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,42.8,178.492)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,46.6769,182.369)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,46.6769,182.369)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,46.6769,182.369)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="15" font-family="Ubuntu" font-size="11" font-weight="700" font-style="normal"
>This method read all files from storage</text>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="28" font-family="Ubuntu" font-size="11" font-weight="700" font-style="normal"
>locations. </text>
<text fill="#000000" fill-opacity="1" stroke="none" xml:space="preserve" x="4" y="42" font-family="Ubuntu" font-size="11" font-weight="700" font-style="normal"
>Where a name of file it is key of DataKey.</text>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,46.6769,182.369)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,46.6769,182.369)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,46.6769,182.369)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(0.969231,0,0,0.969231,46.6769,182.369)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
<g fill="none" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="Ubuntu" font-size="11" font-weight="400" font-style="normal"
>
</g>
</g>
</svg>

Before

(image error) Size: 46 KiB

@ -1,544 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<qmt>
<project>
<uid>{578fb64c-d647-45d7-9413-1a54b354db2b}</uid>
<root-package>
<instance>
<MPackage>
<base-MObject>
<MObject>
<base-MElement>
<MElement>
<uid>{3cc6cd6f-0ce7-43b5-8a8c-1962b0207c79}</uid>
</MElement>
</base-MElement>
<name>KeyStorageImplementation</name>
<children>
<handles>
<handles>
<qlist>
<item>
<handle>
<uid>{1ee7a90d-8a76-4fbd-9bd2-ef7a78f293e9}</uid>
<target>
<instance type="MCanvasDiagram">
<MCanvasDiagram>
<base-MDiagram>
<MDiagram>
<base-MObject>
<MObject>
<base-MElement>
<MElement>
<uid>{1ee7a90d-8a76-4fbd-9bd2-ef7a78f293e9}</uid>
</MElement>
</base-MElement>
<name>KeyStorageImplementation</name>
</MObject>
</base-MObject>
<elements>
<qlist>
<item>
<instance type="DItem">
<DItem>
<base-DObject>
<DObject>
<base-DElement>
<DElement>
<uid>{73bb3bc5-3604-4108-9eb9-6322ee2c03a6}</uid>
</DElement>
</base-DElement>
<object>{5bf04cca-9103-4df5-a5a6-42ca6a7478cd}</object>
<name>Storage Location</name>
<pos>x:585;y:320</pos>
<rect>x:-95;y:-100;w:190;h:200</rect>
<auto-sized>false</auto-sized>
<visual-role>0</visual-role>
</DObject>
</base-DObject>
<variety>artifact</variety>
<shape-editable>false</shape-editable>
</DItem>
</instance>
</item>
<item>
<instance type="DItem">
<DItem>
<base-DObject>
<DObject>
<base-DElement>
<DElement>
<uid>{63906c75-b844-49ff-a2d7-003d91396628}</uid>
</DElement>
</base-DElement>
<object>{54a04999-4d1f-474d-b713-b41960caad2f}</object>
<name>KeyData</name>
<pos>x:530;y:265</pos>
<rect>x:-20;y:-30;w:40;h:60</rect>
<visual-role>0</visual-role>
</DObject>
</base-DObject>
<variety>document</variety>
<shape-editable>false</shape-editable>
</DItem>
</instance>
</item>
<item>
<instance type="DItem">
<DItem>
<base-DObject>
<DObject>
<base-DElement>
<DElement>
<uid>{4ba1d96e-4bb2-490f-9a2c-30f37cab8090}</uid>
</DElement>
</base-DElement>
<object>{7bf70bc2-48c6-4a73-8c37-c4d74c2a471c}</object>
<name>KeyData2</name>
<pos>x:635;y:265</pos>
<rect>x:-20;y:-30;w:40;h:60</rect>
<visual-role>0</visual-role>
</DObject>
</base-DObject>
<variety>document</variety>
<shape-editable>false</shape-editable>
</DItem>
</instance>
</item>
<item>
<instance type="DItem">
<DItem>
<base-DObject>
<DObject>
<base-DElement>
<DElement>
<uid>{f3c8b82c-2d10-4aab-bf2d-f0a773b1a214}</uid>
</DElement>
</base-DElement>
<object>{272fa499-b8f6-4b5f-a65d-52e94fd19e75}</object>
<name>KeyData3</name>
<pos>x:530;y:355</pos>
<rect>x:-20;y:-30;w:40;h:60</rect>
<visual-role>0</visual-role>
</DObject>
</base-DObject>
<variety>document</variety>
<shape-editable>false</shape-editable>
</DItem>
</instance>
</item>
<item>
<instance type="DItem">
<DItem>
<base-DObject>
<DObject>
<base-DElement>
<DElement>
<uid>{0a31881d-976f-49b4-84bc-6e829fde7524}</uid>
</DElement>
</base-DElement>
<object>{41a62eef-b99a-4292-9a5e-6877f3822d74}</object>
<name>KeyData3</name>
<pos>x:635;y:355</pos>
<rect>x:-20;y:-30;w:40;h:60</rect>
<visual-role>0</visual-role>
</DObject>
</base-DObject>
<variety>document</variety>
<shape-editable>false</shape-editable>
</DItem>
</instance>
</item>
<item>
<instance type="DItem">
<DItem>
<base-DObject>
<DObject>
<base-DElement>
<DElement>
<uid>{90e23bca-830b-4f04-9b79-d2b76aa7a942}</uid>
</DElement>
</base-DElement>
<object>{2ccda0b5-00de-4d4c-b365-e045dc6f6f31}</object>
<name>Node (Server or Client)</name>
<pos>x:235;y:290</pos>
<rect>x:-175;y:-130;w:350;h:260</rect>
<auto-sized>false</auto-sized>
<visual-role>0</visual-role>
<visual-emphasized>true</visual-emphasized>
</DObject>
</base-DObject>
<variety>node</variety>
<shape-editable>false</shape-editable>
</DItem>
</instance>
</item>
<item>
<instance type="DClass">
<DClass>
<base-DObject>
<DObject>
<base-DElement>
<DElement>
<uid>{32b0ae69-b40c-426c-aaa8-34d737714611}</uid>
</DElement>
</base-DElement>
<object>{962cbac6-7959-42e9-acd3-f26976cbe484}</object>
<context>AbstractSpace</context>
<name>KeyStorage</name>
<pos>x:235;y:300</pos>
<rect>x:-155;y:-95;w:310;h:190</rect>
<auto-sized>false</auto-sized>
<visual-role>0</visual-role>
</DObject>
</base-DObject>
<namespace>QH</namespace>
</DClass>
</instance>
</item>
<item>
<instance type="DDependency">
<DDependency>
<base-DRelation>
<DRelation>
<base-DElement>
<DElement>
<uid>{18d07b5f-7a24-4007-811a-800f28514869}</uid>
</DElement>
</base-DElement>
<object>{58bd3970-0d20-48e4-ad00-e9b89ee16e8e}</object>
<a>{b11fad66-7c15-4a0c-90d7-fdb7c7b09d54}</a>
<b>{73bb3bc5-3604-4108-9eb9-6322ee2c03a6}</b>
</DRelation>
</base-DRelation>
<direction>2</direction>
</DDependency>
</instance>
</item>
<item>
<instance type="DItem">
<DItem>
<base-DObject>
<DObject>
<base-DElement>
<DElement>
<uid>{b11fad66-7c15-4a0c-90d7-fdb7c7b09d54}</uid>
</DElement>
</base-DElement>
<object>{7c08d894-d147-4b48-8829-6f3a50c45cd0}</object>
<context>AbstractSpace</context>
<name>ReadAllData methods</name>
<pos>x:235;y:320</pos>
<rect>x:-140;y:-50;w:280;h:100</rect>
<auto-sized>false</auto-sized>
<visual-role>0</visual-role>
</DObject>
</base-DObject>
<shape-editable>false</shape-editable>
</DItem>
</instance>
</item>
<item>
<instance type="DAnnotation">
<DAnnotation>
<base-DElement>
<DElement>
<uid>{ac8b121e-fdfc-41ae-bc0b-296e2658c1dc}</uid>
</DElement>
</base-DElement>
<text>This method read all files from storage locations.
Where a name of file it is key of DataKey.</text>
<pos>x:99;y:300</pos>
<rect>x:0;y:0;w:270.125;h:57</rect>
<auto-sized>false</auto-sized>
<visual-role>3</visual-role>
</DAnnotation>
</instance>
</item>
</qlist>
</elements>
<last-modified>1600928388806</last-modified>
<toolbarid>General</toolbarid>
</MDiagram>
</base-MDiagram>
</MCanvasDiagram>
</instance>
</target>
</handle>
</item>
<item>
<handle>
<uid>{5bf04cca-9103-4df5-a5a6-42ca6a7478cd}</uid>
<target>
<instance type="MItem">
<MItem>
<base-MObject>
<MObject>
<base-MElement>
<MElement>
<uid>{5bf04cca-9103-4df5-a5a6-42ca6a7478cd}</uid>
</MElement>
</base-MElement>
<name>Storage Location</name>
</MObject>
</base-MObject>
<variety-editable>false</variety-editable>
<variety>artifact</variety>
</MItem>
</instance>
</target>
</handle>
</item>
<item>
<handle>
<uid>{b4753b9b-bb59-4797-8201-0e7f6cc3a09f}</uid>
<target>
<instance type="MItem">
<MItem>
<base-MObject>
<MObject>
<base-MElement>
<MElement>
<uid>{b4753b9b-bb59-4797-8201-0e7f6cc3a09f}</uid>
</MElement>
</base-MElement>
<name>Новый Document</name>
</MObject>
</base-MObject>
<variety-editable>false</variety-editable>
<variety>document</variety>
</MItem>
</instance>
</target>
</handle>
</item>
<item>
<handle>
<uid>{54a04999-4d1f-474d-b713-b41960caad2f}</uid>
<target>
<instance type="MItem">
<MItem>
<base-MObject>
<MObject>
<base-MElement>
<MElement>
<uid>{54a04999-4d1f-474d-b713-b41960caad2f}</uid>
</MElement>
</base-MElement>
<name>KeyData</name>
</MObject>
</base-MObject>
<variety-editable>false</variety-editable>
<variety>document</variety>
</MItem>
</instance>
</target>
</handle>
</item>
<item>
<handle>
<uid>{7bf70bc2-48c6-4a73-8c37-c4d74c2a471c}</uid>
<target>
<instance type="MItem">
<MItem>
<base-MObject>
<MObject>
<base-MElement>
<MElement>
<uid>{7bf70bc2-48c6-4a73-8c37-c4d74c2a471c}</uid>
</MElement>
</base-MElement>
<name>KeyData2</name>
</MObject>
</base-MObject>
<variety-editable>false</variety-editable>
<variety>document</variety>
</MItem>
</instance>
</target>
</handle>
</item>
<item>
<handle>
<uid>{272fa499-b8f6-4b5f-a65d-52e94fd19e75}</uid>
<target>
<instance type="MItem">
<MItem>
<base-MObject>
<MObject>
<base-MElement>
<MElement>
<uid>{272fa499-b8f6-4b5f-a65d-52e94fd19e75}</uid>
</MElement>
</base-MElement>
<name>KeyData3</name>
</MObject>
</base-MObject>
<variety-editable>false</variety-editable>
<variety>document</variety>
</MItem>
</instance>
</target>
</handle>
</item>
<item>
<handle>
<uid>{41a62eef-b99a-4292-9a5e-6877f3822d74}</uid>
<target>
<instance type="MItem">
<MItem>
<base-MObject>
<MObject>
<base-MElement>
<MElement>
<uid>{41a62eef-b99a-4292-9a5e-6877f3822d74}</uid>
</MElement>
</base-MElement>
<name>KeyData3</name>
</MObject>
</base-MObject>
<variety-editable>false</variety-editable>
<variety>document</variety>
</MItem>
</instance>
</target>
</handle>
</item>
<item>
<handle>
<uid>{2ccda0b5-00de-4d4c-b365-e045dc6f6f31}</uid>
<target>
<instance type="MItem">
<MItem>
<base-MObject>
<MObject>
<base-MElement>
<MElement>
<uid>{2ccda0b5-00de-4d4c-b365-e045dc6f6f31}</uid>
</MElement>
</base-MElement>
<name>Node (Server or Client)</name>
</MObject>
</base-MObject>
<variety-editable>false</variety-editable>
<variety>node</variety>
</MItem>
</instance>
</target>
</handle>
</item>
<item>
<handle>
<uid>{d472d214-54c2-4045-b825-9a2ab109d69f}</uid>
<target>
<instance type="MPackage">
<MPackage>
<base-MObject>
<MObject>
<base-MElement>
<MElement>
<uid>{d472d214-54c2-4045-b825-9a2ab109d69f}</uid>
<flags>1</flags>
</MElement>
</base-MElement>
<name>AbstractSpace</name>
<children>
<handles>
<handles>
<qlist>
<item>
<handle>
<uid>{962cbac6-7959-42e9-acd3-f26976cbe484}</uid>
<target>
<instance type="MClass">
<MClass>
<base-MObject>
<MObject>
<base-MElement>
<MElement>
<uid>{962cbac6-7959-42e9-acd3-f26976cbe484}</uid>
<flags>1</flags>
</MElement>
</base-MElement>
<name>KeyStorage</name>
</MObject>
</base-MObject>
<namespace>QH</namespace>
</MClass>
</instance>
</target>
</handle>
</item>
<item>
<handle>
<uid>{7c08d894-d147-4b48-8829-6f3a50c45cd0}</uid>
<target>
<instance type="MItem">
<MItem>
<base-MObject>
<MObject>
<base-MElement>
<MElement>
<uid>{7c08d894-d147-4b48-8829-6f3a50c45cd0}</uid>
</MElement>
</base-MElement>
<name>ReadAllData methods</name>
<relations>
<handles>
<handles>
<qlist>
<item>
<handle>
<uid>{58bd3970-0d20-48e4-ad00-e9b89ee16e8e}</uid>
<target>
<instance type="MDependency">
<MDependency>
<base-MRelation>
<MRelation>
<base-MElement>
<MElement>
<uid>{58bd3970-0d20-48e4-ad00-e9b89ee16e8e}</uid>
</MElement>
</base-MElement>
<a>{7c08d894-d147-4b48-8829-6f3a50c45cd0}</a>
<b>{5bf04cca-9103-4df5-a5a6-42ca6a7478cd}</b>
</MRelation>
</base-MRelation>
<direction>2</direction>
</MDependency>
</instance>
</target>
</handle>
</item>
</qlist>
</handles>
</handles>
</relations>
</MObject>
</base-MObject>
</MItem>
</instance>
</target>
</handle>
</item>
</qlist>
</handles>
</handles>
</children>
</MObject>
</base-MObject>
</MPackage>
</instance>
</target>
</handle>
</item>
</qlist>
</handles>
</handles>
</children>
</MObject>
</base-MObject>
</MPackage>
</instance>
</root-package>
</project>
</qmt>

@ -316,6 +316,29 @@ bool AbstractNode::generateRSAforSSL(EVP_PKEY *pkey) const {
return false;
}
//#if OPENSSL_VERSION_MAJOR >= 3
// EVP_PKEY_CTX *pctx =
// EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
// unsigned int primes = 3;
// unsigned int bits = 4096;
// OSSL_PARAM params[3];
// pkey = EVP_RSA_gen(4096);
// EVP_PKEY_keygen_init(pctx);
// params[0] = OSSL_PARAM_construct_uint("bits", &bits);
// params[1] = OSSL_PARAM_construct_uint("primes", &primes);
// params[2] = OSSL_PARAM_construct_end();
// EVP_PKEY_CTX_set_params(pctx, params);
// EVP_PKEY_generate(pctx, &pkey);
// EVP_PKEY_CTX_free(pctx);
//#else
BIGNUM * bn = BN_new();
int rc = BN_set_word(bn, RSA_F4);
@ -334,7 +357,7 @@ bool AbstractNode::generateRSAforSSL(EVP_PKEY *pkey) const {
q_check_ptr(rsa);
if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0)
return false;
//#endif
return true;
}
@ -884,9 +907,7 @@ bool AbstractNode::ping(const HostAddress &address) {
}
bool AbstractNode::isBanned(QAbstractSocket *socket) const {
auto info = getInfoPtr(HostAddress{socket->peerAddress(), socket->peerPort()});
bool AbstractNode::isBanned(const AbstractNodeInfo *info) const {
if (!(info && info->isValid())) {
return false;
}
@ -911,7 +932,7 @@ void AbstractNode::incomingConnection(qintptr handle) {
socket->setSocketDescriptor(handle);
if (isBanned(socket)) {
if (isBanned(getInfoPtr(HostAddress{socket->peerAddress(), socket->peerPort()}))) {
QuasarAppUtils::Params::log("Income connection from banned address",
QuasarAppUtils::Error);
@ -1115,14 +1136,6 @@ QSharedPointer<AbstractData> AbstractNode::prepareData(const Package &pkg) const
return value;
}
QSharedPointer<AbstractData> AbstractNode::genPackage(unsigned short cmd) const {
return QSharedPointer<AbstractData>(_registeredTypes.value(cmd, [](){return nullptr;})());
}
bool AbstractNode::checkCommand(unsigned short cmd) const {
return _registeredTypes.contains(cmd);
}
QList<HostAddress> AbstractNode::connectionsList() const {
QMutexLocker locer(&_connectionsMutex);

@ -27,8 +27,6 @@
#include "abstractdata.h"
#include "workstate.h"
#include "package.h"
#include "cryptopairkeys.h"
#include "icrypto.h"
#include "heart_global.h"
#include "packagemanager.h"
#include "abstracterrorcodes.h"
@ -508,7 +506,7 @@ protected:
* @param socket This is node info object for validation.
* @return true if node is banned.
*/
bool isBanned(QAbstractSocket* socket) const;
virtual bool isBanned(const AbstractNodeInfo *socket) const;
/**
* @brief incomingConnection This is ovverided method of QTCPServer.
@ -595,18 +593,6 @@ protected:
*/
virtual void nodeDisconnected(AbstractNodeInfo *node);
template<class T>
/**
* @brief registerPackageType This method register package type T.
* This is need to prepare pacakge for parsing in the parsePackage method.
*/
void registerPackageType() {
_registeredTypes[T::command()] = [](){
return new T();
};
};
void prepareForDelete() override;
/**
@ -617,23 +603,6 @@ protected:
*/
QSharedPointer<PKG::AbstractData> prepareData(const Package& pkg) const;
/**
* @brief genPackage This is factory method that generate data pacakge objects by command.
* All object should be registered before using this method.
* @param cmd This is command of pacakge see Header::command.
* @return shared pointer to new data object.
* @see AbstractNode::registerPackageType
* @see Header::command
*/
QSharedPointer<PKG::AbstractData> genPackage(unsigned short cmd) const ;
/**
* @brief checkCommand This method check command are if registered type or not.
* @brief cmd This is command of a verifiable package.
* @return True if the package is registered in a node.
*/
bool checkCommand(unsigned short cmd) const;
/**
* @brief connectionsList This method return list of all node connections
* @return list of node connections.
@ -674,7 +643,7 @@ protected slots:
* @param errorString This is string value of the error.
* @note default implementation do nothing. Override this method if you want to handle nodes network errors.
*/
virtual void nodeErrorOccured(AbstractNodeInfo *nodeInfo,
virtual void nodeErrorOccured(QH::AbstractNodeInfo *nodeInfo,
QAbstractSocket::SocketError errorCode,
QString errorString);
@ -686,12 +655,12 @@ protected slots:
* Overrid this method for handle ssl errors on this node or server.
* @param error This is error that occured..
*/
virtual void handleSslErrorOcurred(SslSocket *scket, const QSslError& error);
virtual void handleSslErrorOcurred(QH::SslSocket *scket, const QSslError& error);
#endif
private slots:
void avelableBytes(AbstractNodeInfo* sender);
void avelableBytes(QH::AbstractNodeInfo* sender);
/**
* @brief handleNodeStatusChanged This method invoked when status of peer node chganged.
@ -699,7 +668,7 @@ private slots:
* @param status This is new status of node.
*
*/
void handleNodeStatusChanged(AbstractNodeInfo* node, NodeCoonectionStatus status);
void handleNodeStatusChanged(QH::AbstractNodeInfo* node, QH::NodeCoonectionStatus status);
/**
* @brief handleWorkerStoped
@ -710,7 +679,7 @@ private slots:
* @brief handleForceRemoveNode - force remove connection.
* @param node
*/
void handleForceRemoveNode(HostAddress node);
void handleForceRemoveNode(QH::HostAddress node);
/**
* @brief handleBeginWork This method run task on new thread.
@ -725,12 +694,12 @@ private slots:
* Default implementation just pront error messages
* @param errors This is errors list.
*/
void handleSslErrorOcurredPrivate(SslSocket *sender, const QList<QSslError> & errors);
void handleSslErrorOcurredPrivate(QH::SslSocket *sender, const QList<QSslError> & errors);
/**
* @brief handleEncrypted invoke when a ssl socket is encripted!
*/
void handleEncrypted(AbstractNodeInfo *node);
void handleEncrypted(QH::AbstractNodeInfo *node);
#endif
@ -796,7 +765,6 @@ private:
mutable QMutex _workersMutex;
QThreadPool *_threadPool = nullptr;
QHash<unsigned short, std::function<PKG::AbstractData*()>> _registeredTypes;
friend class WebSocketController;
friend class SocketFactory;

@ -1,90 +0,0 @@
/*
* Copyright (C) 2021-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "asynckeysauth.h"
#include "QCryptographicHash"
#include <QString>
#include <time.h>
namespace QH {
AsyncKeysAuth::AsyncKeysAuth() {
}
bool AsyncKeysAuth::auth(int allowedTimeRangeSec, QString* userId) const {
int diff = time(0) - _unixTime;
if (diff < 0) {
return false;
}
if (diff >= allowedTimeRangeSec) {
return false;
}
QByteArray data = _publicKey;
data.insert(0, reinterpret_cast<const char*>(&_unixTime),
sizeof(_unixTime));
bool result = checkSign(data, _signature, _publicKey);
if (result && userId) {
*userId = getUserId();
}
return result;
}
bool AsyncKeysAuth::prepare() {
_unixTime = time(0);
QByteArray data = _publicKey;
data.insert(0, reinterpret_cast<const char*>(&_unixTime),
sizeof(_unixTime));
setSignature(signMessage(data, getPrivateKey()));
return isValid();
}
unsigned int AsyncKeysAuth::unixTime() const {
return _unixTime;
}
void AsyncKeysAuth::setUnixTime(unsigned int newUnixTime) {
_unixTime = newUnixTime;
}
const QByteArray &AsyncKeysAuth::signature() const {
return _signature;
}
const QByteArray &AsyncKeysAuth::publicKey() const {
return _publicKey;
}
void AsyncKeysAuth::setPublicKey(const QByteArray &newPublicKey) {
_publicKey = newPublicKey;
}
bool AsyncKeysAuth::isValid() const {
return _publicKey.size() && _signature.size() && _unixTime;
}
QString AsyncKeysAuth::getUserId() const {
return QCryptographicHash::hash(_publicKey,
QCryptographicHash::Sha256).
toBase64(QByteArray::Base64UrlEncoding);
}
void AsyncKeysAuth::setSignature(const QByteArray &newSignature) {
_signature = newSignature;
}
}

@ -1,81 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "cryptopairkeys.h"
#include <QDataStream>
namespace QH {
CryptoPairKeys::CryptoPairKeys() {
}
CryptoPairKeys::CryptoPairKeys(const QByteArray &pubKey, const QByteArray &privKey) {
setPrivKey(privKey);
setPublicKey(pubKey);
setBits(privKey.size() * 8);
}
bool CryptoPairKeys::isValid() const {
return _privKey.size() && _publicKey.size() && !(_bits % 8) && _bits > 1;
}
QByteArray CryptoPairKeys::privKey() const {
return _privKey;
}
void CryptoPairKeys::setPrivKey(const QByteArray &privKey) {
_privKey = privKey;
}
QByteArray CryptoPairKeys::publicKey() const {
return _publicKey;
}
void CryptoPairKeys::setPublicKey(const QByteArray &publicKey) {
_publicKey = publicKey;
}
int CryptoPairKeys::bits() const {
return _bits;
}
void CryptoPairKeys::setBits(int bits) {
_bits = bits;
}
QDataStream &CryptoPairKeys::fromStream(QDataStream &stream) {
stream >> _publicKey;
stream >> _privKey;
stream >> _bits;
return stream;
}
QDataStream &CryptoPairKeys::toStream(QDataStream &stream) const {
stream << _publicKey;
stream << _privKey;
stream << _bits;
return stream;
}
bool operator ==(const CryptoPairKeys &left, const CryptoPairKeys &right) {
return !(left != right);
}
bool operator !=(const CryptoPairKeys &left, const CryptoPairKeys &right) {
return left._privKey != right._privKey || left._publicKey != right._publicKey;
}
uint qHash(const CryptoPairKeys &value) {
return qHash(value.privKey());
}
}

@ -1,90 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef CRYPTOPAIRKEYS_H
#define CRYPTOPAIRKEYS_H
#include "streambase.h"
namespace QH {
/**
* @brief The CryptoPairKeys class contains pair keys. This is wraper for cripto graphick keys.
*/
class HEARTSHARED_EXPORT CryptoPairKeys: public StreamBase
{
public:
CryptoPairKeys();
CryptoPairKeys(const QByteArray& pubKey, const QByteArray& privKey);
/**
* @brief isValid - This Method check an internal keys.
* @return true if this objeсt contains a valid pair keys.
*/
bool isValid() const;
/**
* @brief privKey This method return private key of current keys pair.
* @return return byteArray of private key.
*/
QByteArray privKey() const;
/**
* @brief setPrivKey This method set a private key for keys pair.
* @param privKey new byte array of private pair keys.
*/
void setPrivKey(const QByteArray &privKey);
/**
* @brief publicKey This method return public key of array.
* @return publicKey of current key pair.
*/
QByteArray publicKey() const;
/**
* @brief setPublicKey This method set new value of publickKey.
* @param publicKey new value of publicKey.
*/
void setPublicKey(const QByteArray &publicKey);
/**
* @brief bits This method return size pair of crypto keys in bits.
* @return bits size of keys pair.
*/
int bits() const;
/**
* @brief setBits This method sets new value of keys pair.
* @param bits This is new value of size keys.
*/
void setBits(int bits);
friend bool operator != (const CryptoPairKeys& left, const CryptoPairKeys& right);
friend bool operator == (const CryptoPairKeys& left, const CryptoPairKeys& right);
// StreamBase interface
protected:
QDataStream &fromStream(QDataStream &stream);
QDataStream &toStream(QDataStream &stream) const;
private:
QByteArray _privKey;
QByteArray _publicKey;
int _bits;
};
/**
* @brief qHash This functions calc crc32 hash code of CryptoPairKeys object.
* @param value -
* @return crc32 hash code.
*/
uint qHash(const CryptoPairKeys& value);
}
#endif // CRYPTOPAIRKEYS_H

@ -6,7 +6,7 @@
//#
#include "authecdsa.h"
#include "ecdsassl11.h"
#ifdef USE_HEART_SSL
@ -16,13 +16,14 @@
#include <openssl/err.h>
#include <QCryptographicHash>
#include <QDataStream>
#include <QIODevice>
#include <QVector>
#include <quasarapp.h>
namespace QH {
AuthECDSA::AuthECDSA() {
ECDSASSL11::ECDSASSL11() {
}
@ -79,7 +80,7 @@ QByteArray extractPublicKey(EC_KEY* key, EC_GROUP* group) {
return data;
}
bool AuthECDSA::makeKeys(QByteArray &pubKey, QByteArray &privKey) {
bool ECDSASSL11::makeKeys(QByteArray &pubKey, QByteArray &privKey) {
EC_KEY *eckey= nullptr;
EC_GROUP *ecgroup = nullptr;
@ -101,7 +102,7 @@ bool AuthECDSA::makeKeys(QByteArray &pubKey, QByteArray &privKey) {
return pubKey.length() && privKey.length();
}
QByteArray AuthECDSA::signMessage(const QByteArray &inputData,
QByteArray ECDSASSL11::signMessage(const QByteArray &inputData,
const QByteArray &key) const {
EC_KEY *eckey= nullptr;
@ -147,7 +148,7 @@ QByteArray AuthECDSA::signMessage(const QByteArray &inputData,
return result;
}
bool AuthECDSA::checkSign(const QByteArray &inputData,
bool ECDSASSL11::checkSign(const QByteArray &inputData,
const QByteArray &signature,
const QByteArray &key) const {
@ -198,7 +199,15 @@ bool AuthECDSA::checkSign(const QByteArray &inputData,
}
bool AuthECDSA::prepareKeyAdnGroupObjects(EC_KEY **eckey, EC_GROUP **ecgroup) {
QByteArray ECDSASSL11::decript(const QByteArray &message, const QByteArray &key) {
return {};
}
QByteArray ECDSASSL11::encript(const QByteArray &message, const QByteArray &key) {
return {};
}
bool ECDSASSL11::prepareKeyAdnGroupObjects(EC_KEY **eckey, EC_GROUP **ecgroup) {
// input data should be valid pointers to pointers of key and group objects.
if (!(eckey && ecgroup))

@ -6,28 +6,27 @@
//#
#ifndef AUTHECDSA_H
#define AUTHECDSA_H
#ifndef QH_ECDSA_SSL_1_1_H
#define QH_ECDSA_SSL_1_1_H
#include "heart_global.h"
#ifdef USE_HEART_SSL
#include "abstractdata.h"
#include <asynckeysauth.h>
#include "icrypto.h"
#include <openssl/ec.h> // for EC_GROUP_new_by_curve_name, EC_GROUP_free, EC_KEY_new, EC_KEY_set_group, EC_KEY_generate_key,EC_KEY_free
namespace QH {
/**
* @brief The AuthECDSA class is ecdsa implementation of the Async authentication. This implementation based on Openssl library.
* @brief The ECDSASSL11 class is ecdsa implementation of the Async authentication. This implementation based on Openssl library.
* @note This class compatibility only with ssl 1.1 and ssl 3.0 (depricated fundtions).
*/
class HEARTSHARED_EXPORT AuthECDSA: public QH::AsyncKeysAuth
class HEARTSHARED_EXPORT ECDSASSL11: public QH::ICrypto
{
public:
AuthECDSA();
ECDSASSL11();
/**
* @brief makeKeys This static method generate the public and private keys of the ECDSA.
@ -37,19 +36,29 @@ public:
*/
static bool makeKeys(QByteArray &pubKey, QByteArray &privKey);
// AsyncKeysAuth interface
protected:
QByteArray signMessage(const QByteArray &inputData, const QByteArray &key) const override;
bool checkSign(const QByteArray &inputData, const QByteArray &signature, const QByteArray &key) const override;
/**
* @brief decript This method has empty implementation.
* @return empty array.
*/
QByteArray decript(const QByteArray &message, const QByteArray &key) override;
/**
* @brief encript This method has empty implementation.
* @return empty array.
*/
QByteArray encript(const QByteArray &message, const QByteArray &key) override;
private:
static bool prepareKeyAdnGroupObjects(EC_KEY **eckey, EC_GROUP **ecgroup);
};
};
}
#endif
#endif // AUTHECDSA_H
#endif // QH_ECDSA_SSL_1_1_H

@ -11,8 +11,4 @@
namespace QH {
ICrypto::ICrypto() = default;
ICrypto::~ICrypto() = default;
}

@ -0,0 +1,65 @@
/*
* Copyright (C) 2021-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef I_CRYPTO_H
#define I_CRYPTO_H
#include "heart_global.h"
#include <QByteArray>
namespace QH {
/**
* @brief The ICrypto class This is base interface that provide encription functionality.
*/
class HEARTSHARED_EXPORT ICrypto
{
protected:
/**
* @brief decript This method decript @a message using @a key.
* @param message This is encripted message that should be decripted.
* @param key This is key that will be used for decription for the @a message.
* @return decripted message or empty string if method not supported or decripted failed.
* @see IAsyncEncription::encript
*/
virtual QByteArray decript(const QByteArray& message, const QByteArray& key) = 0;
/**
* @brief decript This method encript @a message using @a key.
* @param message This is a message that should be decripted.
* @param key This is key that will be used for encription for the @a message.
* @return decripted message or empty string if method not supported or decripted failed.
* @see IAsyncEncription::encript
*/
virtual QByteArray encript(const QByteArray& message, const QByteArray& key) = 0;
/**
* @brief signMessage This method should be sign the @a message using the @a key.
* @param message This is input data that should be signed.
* @param key This is a privete key for encription the @a message.
* @return signature data array.
* @see AsyncKeysAuth::descrupt
*/
virtual QByteArray signMessage(const QByteArray& message, const QByteArray& key) const = 0;
/**
* @brief checkSign This method should be check signature of the @a message using the @a key.
* @param message This is input data that should be decripted.
* @param signature This is signature that will be checked for the @a message.
* @param key This is a public key for encription the @a inpputData.
* @return decripted data array.
* @see AsyncKeysAuth::encrypt
*/
virtual bool checkSign(const QByteArray& message,
const QByteArray& signature,
const QByteArray& key) const = 0;
};
}
#endif // I_CRYPTO_H

@ -8,14 +8,27 @@
#ifndef ASYNCKEYSAUTH_H
#define ASYNCKEYSAUTH_H
#include <QByteArray>
#include <QCryptographicHash>
#include <time.h>
#include <QString>
#include "heart_global.h"
namespace QH {
/**
* @brief The AsyncKeysAuth class is base class for works with authorization of a pair of asynchronous keys
* @brief The AsyncKeysAuth class is temaplate class for works with authorization of a pair of asynchronous keys
* This class contains base implementation for the authentication using async encription. The base encription alhorithm defined on the template argument **CryptoImplementation**.
* You can use any crypto alhorithm.
*
* ## Exampel of use:
*
* @code{cpp}
* #include <hcrypto.h>
*
* using ECDSAAuth = AsyncKeysAuth<ECDSA>;
*
* @endcode
*
*
* ### How to it works:
*
@ -46,45 +59,115 @@ namespace QH {
* * After accept server create new user with ID = sha256(PUB) or
* if user alredy exits make them as a logined user.
*
* @tparam CryptoImplementation This is internal implementaion of base encription functions.
* @see iCrypto class.
*
*/
class HEARTSHARED_EXPORT AsyncKeysAuth
template<class CryptoImplementation>
class AsyncKeysAuth: public CryptoImplementation
{
public:
AsyncKeysAuth();
AsyncKeysAuth() {
}
~AsyncKeysAuth() {
}
/**
* @brief auth This method make authentication and return true if the authentication finished successful else false.
* @brief retLoginedUserId This is logined user id in Base64UrlEncoding
* @return true if the authentication finished successful else false.
*/
bool auth(int allowedTimeRangeSec, QString* retLoginedUserId) const;
bool auth(int allowedTimeRangeSec, QString* retLoginedUserId) const {
int diff = time(0) - _unixTime;
if (diff < 0) {
return false;
}
if (diff >= allowedTimeRangeSec) {
return false;
}
QByteArray data = _publicKey;
data.insert(0, reinterpret_cast<const char*>(&_unixTime),
sizeof(_unixTime));
bool result = checkSign(data, _signature, _publicKey);
if (result && retLoginedUserId) {
*retLoginedUserId = getUserId();
}
return result;
}
/**
* @brief prepare This method will generate signature for autentication of client. Please inboke this method before send request to server.
* @return true if signature generated sucessuful.
*/
bool prepare();
bool prepare() {
_unixTime = time(0);
QByteArray data = _publicKey;
data.insert(0, reinterpret_cast<const char*>(&_unixTime),
sizeof(_unixTime));
setSignature(signMessage(data, getPrivateKey()));
return isValid();
}
/**
* @brief unixTime This method return unix time that client added for authentication.
* @return unix time that client added for authentication.
* @see AsyncKeysAuth::setUnixTime
*/
unsigned int unixTime() const;
unsigned int unixTime() const {
return _unixTime;
}
/**
* @brief setUnixTime This method sets new value of the unixTime propertye.
* @param newUnixTime This is new unix time value. Unix time sets in secunds from 1970 year
*/
void setUnixTime(unsigned int newUnixTime);
void setUnixTime(unsigned int newUnixTime) {
_unixTime = newUnixTime;
}
/**
* @brief signature This method return signature array.
* @return signature array.
* @see AsyncKeysAuth::setSignature
*/
const QByteArray &signature() const;
const QByteArray &signature() const {
return _signature;
}
/**
* @brief isValid this method check this ibject to valid.
* @return return true if object contains valid signature else false.
* @note Invoke the AsyncKeysAuth::prepare method before check valid of object. All object that not be preparred is invalid.
*/
bool isValid() const {
return _publicKey.size() && _signature.size() && _unixTime;
}
/**
* @brief getUserId This method return user id that generated from the public key.
* @note This function works slow, because this object does not contain ID of user. The user ID will be generated every invoke of this function
* @return user ID.
*/
QString getUserId() const {
return QCryptographicHash::hash(_publicKey,
QCryptographicHash::Sha256).
toBase64(QByteArray::Base64UrlEncoding);
}
/**
* @brief publicKey This method return public key that client added for authentication.
@ -92,49 +175,36 @@ public:
* @return public key that client added for authentication.
* @see AsyncKeysAuth::setPublicKey
*/
const QByteArray &publicKey() const;
const QByteArray &publicKey() const {
return _publicKey;
}
/**
* @brief setPublicKey This method sets new public key for authentication.
* @param newPublicKey Thiy is new key.
* @see AsyncKeysAuth::publicKey
*/
void setPublicKey(const QByteArray &newPublicKey);
/**
* @brief isValid this method check this ibject to valid.
* @return return true if object contains valid signature else false.
* @note Invoke the AsyncKeysAuth::prepare method before check valid of object. All object that not be preparred is invalid.
*/
bool isValid() const;
/**
* @brief getUserId This method return user id that generated from the public key.
* @note This function works slow, because this object does not contain ID of user. The user ID will be generated every invoke of this function
* @return user ID.
*/
QString getUserId() const;
void setPublicKey(const QByteArray &newPublicKey) {
_publicKey = newPublicKey;
}
protected:
/**
* @brief signMessage This method should be sign the @a message using the @a key.
* @param message This is input data that should be signed.
* @param key This is a privete key for encription the @a message.
* @return signature data array.
* @see AsyncKeysAuth::descrupt
*/
virtual QByteArray signMessage(const QByteArray& message, const QByteArray& key) const = 0;
QByteArray decript(const QByteArray &message, const QByteArray &key) override {
return CryptoImplementation::decript(message, key);
};
/**
* @brief checkSign This method should be check signature of the @a message using the @a key.
* @param message This is input data that should be decripted.
* @param signature This is signature that will be checked for the @a message.
* @param key This is a public key for encription the @a inpputData.
* @return decripted data array.
* @see AsyncKeysAuth::encrypt
*/
virtual bool checkSign(const QByteArray& message, const QByteArray& signature, const QByteArray& key) const = 0;
QByteArray encript(const QByteArray &message, const QByteArray &key) override {
return CryptoImplementation::encript(message, key);
};
QByteArray signMessage(const QByteArray &message, const QByteArray &key) const override {
return CryptoImplementation::signMessage(message, key);
};
bool checkSign(const QByteArray &message, const QByteArray &signature, const QByteArray &key) const override {
return CryptoImplementation::checkSign(message, signature, key);
};
/**
* @brief getPrivateKey This method should be return private key for the public key that saved in this object.
@ -147,7 +217,9 @@ protected:
* @param newSignature new signature value.
* @note used in the
*/
void setSignature(const QByteArray &newSignature);
void setSignature(const QByteArray &newSignature) {
_signature = newSignature;
}
unsigned int _unixTime = 0;
QByteArray _signature;

@ -0,0 +1,31 @@
//#
//# Copyright (C) 2021-2022 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#ifndef AUTHECDSA_H
#define AUTHECDSA_H
#include "heart_global.h"
#ifdef USE_HEART_SSL
#include "hcrypto/ecdsassl11.h"
#include "asynckeysauth.h"
namespace QH {
/**
* @brief The AuthECDSA class is ecdsa implementation of the Async authentication. This implementation based on Openssl library.
*/
typedef AsyncKeysAuth<ECDSASSL11> AuthECDSA;
}
#endif
#endif // AUTHECDSA_H

@ -0,0 +1,22 @@
/*
* Copyright (C) 2021-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef ECDSASIGNER_H
#define ECDSASIGNER_H
#include "signer.h"
#include "hcrypto/ecdsassl11.h"
namespace QH {
/**
* @brief The ECDSASigner class is ecdsa implementation of the Signer class. This implementation based on Openssl library.
*/
typedef Signer<ECDSASSL11> ECDSASigner;
}
#endif // ECDSASIGNER_H

@ -0,0 +1,47 @@
/*
* Copyright (C) 2021-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "isignerdelegate.h"
namespace QH {
ISignerDelegate::ISignerDelegate() {
}
const QByteArray &ISignerDelegate::getSignature() const {
return sign;
}
void ISignerDelegate::setSignature(const QByteArray &newSignature) {
sign = newSignature;
}
const QByteArray &ISignerDelegate::getHash() const {
return hash;
}
void ISignerDelegate::setHash(const QByteArray &newHash) {
hash = newHash;
}
QDataStream &ISignerDelegate::fromStream(QDataStream &stream) {
stream >> hash;
stream >> sign;
return stream;
}
QDataStream &ISignerDelegate::toStream(QDataStream &stream) const {
stream << hash;
stream << sign;
return stream;
}
}

@ -0,0 +1,83 @@
/*
* Copyright (C) 2021-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef ISIGNERDELEGATE_H
#define ISIGNERDELEGATE_H
#include <streambase.h>
namespace QH {
/**
* @brief The ISignerDelegate class This is base class of signer delegate.
* The sisgner class will be invoke all delegate methods for control the input object that need to sign.
* @note This class contasin sign and hash fild and override the >> and << operators for QDataStream,
* so if you want to convert your object to bytes array don not forget invoke the ISignerDelegate::fromStream and ISignerDelegate::toStream methods.
* @see Signer
*/
class ISignerDelegate: public StreamBase
{
public:
ISignerDelegate();
/**
* @brief getSignature This method return constant reference to the signature array.
* @return constant reference to the signature array.
*/
virtual const QByteArray &getSignature() const;
/**
* @brief setSignature This method sets the new signature of this object.
* @param newSignature new signature value.
*/
virtual void setSignature(const QByteArray &newSignature);
/**
* @brief getHash This method return constant reference to the hash array.
* @return constant reference to the signature array.
*/
virtual const QByteArray &getHash() const;
/**
* @brief setHash This method sets the new hash sum of this object.
* @param newSignature new signature value.
*/
virtual void setHash(const QByteArray &newHash);
/**
* @brief getPrivateKey This method should be return private key for the public key that saved in this object.
* @return private key for the public key that saved in this object.
*/
virtual const QByteArray& getPrivateKey() const = 0;
/**
* @brief getPublicKey This method should be return public key for the private key that encrypted this object.
* @return public key for the private key that ecrypt this object.
*/
virtual const QByteArray& getPublicKey() const = 0;
/**
* @brief getMessage This method should be return message that you want to sign.
* @return message that you want to sign.
*/
virtual const QByteArray getMessage() const = 0;
// StreamBase interface
protected:
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
private:
QByteArray hash;
QByteArray sign;
};
}
#endif // ISIGNERDELEGATE_H

@ -0,0 +1,91 @@
/*
* Copyright (C) 2021-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef SIGNER_H
#define SIGNER_H
#include <QByteArray>
#include <QCryptographicHash>
#include <QSharedPointer>
#include "isignerdelegate.h"
#include "qaservice.h"
namespace QH {
/**
* @brief The Signer class can sign and check the signature of the any childs classes of the ISignerDelegate class.
*
* **Exmaple of use**
*
* @code{cpp}
* #include <hcriptoFeatures/isignerdelegate.h>
* #include <hcriptoFeatures/ecdsasigner.h>
*
* class MyDelegate: public ISignerDelegate {
* // override all methods
* };
*
* int main () {
* MyDelegate delegate;
*
* // sign your object
* QH::ECDSASigner::sign(&delegate);
*
* // check signature of the object
* QH::ECDSASigner::check(&delegate);
* }
*
*
* @endcode
*
* @note the MyDelegate class should be contains a public for check signature and a private for sign object keys
* @tparam CryptoImplementation This is internal implementaion of base encription functions.
* @see iCrypto class.
*/
template<class CryptoImplementation>
class Signer: protected QuasarAppUtils::Service<Signer<CryptoImplementation>>,
protected CryptoImplementation
{
public:
Signer() {};
~Signer() {};
/**
* @brief sign This is main method for signing of this object.
* @return true if the object signed sucessful
*/
static bool sign(ISignerDelegate* obj) {
if (auto signer = Signer<CryptoImplementation>::autoInstance()) {
auto sign = signer->signMessage(obj->getMessage(), obj->getPrivateKey());
if (sign.size()) {
obj->setSignature(sign);
return true;
}
}
return false;
};
/**
* @brief check This method check signature of this object.
* @return true if the objec signed
*/
static bool check(const ISignerDelegate* obj) {
if (auto signer = Signer<CryptoImplementation>::autoInstance()) {
return signer->checkSign(obj->getMessage(), obj->signature(), obj->getPublicKey());
}
return false;
};
};
}
#endif // SIGNER_H

@ -30,10 +30,8 @@ HostAddress::HostAddress(const SpecialAddress &other, int port):
setPort(port);
}
HostAddress::HostAddress(const HostAddress &other):
QHostAddress(*static_cast<const HostAddress*>(&other)) {
setPort(other.port());
HostAddress::HostAddress(const HostAddress &other) {
operator=(other);
}
unsigned short HostAddress::port() const {
@ -44,6 +42,13 @@ void HostAddress::setPort(unsigned short port) {
_port = port;
}
HostAddress &HostAddress::operator =(const HostAddress &right) {
QHostAddress::operator=(*static_cast<const QHostAddress*>(&right));
setPort(right.port());
return *this;
}
bool HostAddress::isIP(const QString &address) {
return !QHostAddress{address}.isNull();
}
@ -56,6 +61,22 @@ QString HostAddress::toString() const {
return QHostAddress::toString() + ":" + QString::number(port());
}
QByteArray HostAddress::toBytes() const {
QByteArray res;
QDataStream stream(&res, QIODevice::WriteOnly);
operator <<(stream, *this);
return res;
}
bool HostAddress::fromBytes(const QByteArray &array) {
if (array.isEmpty())
return false;
QDataStream stream(array);
operator >>(stream, *this);
return true;
}
QDataStream &operator >>(QDataStream &stream, HostAddress &address) {
stream >> static_cast<QHostAddress&>(address);
stream >> address._port;

@ -47,6 +47,7 @@ public:
friend bool& operator == (QDataStream& stream, HostAddress& address);
friend bool& operator != (QDataStream& stream, HostAddress& address);
HostAddress& operator = (const HostAddress& right);;
/**
* @brief isIP This method return true if the @a address is valid.
* @brief address This is tring value of the network ip address.
@ -66,8 +67,22 @@ public:
*/
QString toString() const;
/**
* @brief toBytes This method convert a network address to a byte array.
* @return byte array implementation of this object.
*/
QByteArray toBytes() const;
/**
* @brief fromBytes This method applay @a array obejct. (conver a byte array to a newtwork address object)
* @param array this is input array.
* @return true if array applayed successfull
*/
bool fromBytes(const QByteArray& array);
private:
unsigned short _port = 0;
};
uint qHash(const HostAddress& address);

@ -1,105 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef ICRYPTO_H
#define ICRYPTO_H
#include <QList>
#include <QThread>
#include "heart_global.h"
#include <QByteArray>
#include <QHash>
#include <QSet>
#define RAND_KEY ""
class QMutex;
namespace QH {
class CryptoPairKeys;
/**
* @brief The ICrypto class provide cryptographic functionality.
* This is interface for decoration of KeyStorage classes.
*/
class HEARTSHARED_EXPORT ICrypto
{
public:
ICrypto();
virtual ~ICrypto();
/**
* @brief isValid check crypto object is valid.
* @return true if the crypto object is valid.
*/
virtual bool isValid() const = 0;
/**
* @brief crypt This method crypt input data using public key.
* @param data This is pointer to data array for crypting.
* @note data as ben changed after call this method.
* @param publicKey This is key for crypting data.
* @return true if function finished successful.
*/
virtual bool crypt(QByteArray *data, const QByteArray& publicKey) = 0;
/**
* @brief decrypt This method decrypt input data.
* @param cryptedData This is pointer to data array for decrypting.
* @note cryptedData has been changed after call this method.
* @param privateKey This is key for decrypting data message
* @return true if function finished successful.
*/
virtual bool decrypt(QByteArray *cryptedData, const QByteArray& privateKey) = 0;
/**
* @brief sign This method sign a input message using privateKey.
* @param data This is pointer to data array for signed.
* @note data has been changed after call this method.
* @param privateKey This is key for sign a message.
* @return true if function finished successful.
*/
virtual bool sign(QByteArray* data, const QByteArray& privateKey) = 0;
/**
* @brief extractSign This method extract sign from signed byteArray.
* @param data - signed message.
* @return return array of sign.
*/
virtual QByteArray extractSign(const QByteArray& data) = 0;
/**
* @brief concatSign This method make a concatenation between a message data and a sign of message.
* @param data This is message data.
* @param sign This is sign of message.
* @return signed message.
*/
virtual QByteArray concatSign(const QByteArray& data, const QByteArray& sign) = 0;
/**
* @brief check This method validation signed message
* @param signedData This is array of signed data.
* @param publicKey This is public key for validation of message.
* @return true if function finished successful and signedData is valid.
*/
virtual bool check(const QByteArray& signedData, const QByteArray& publicKey) = 0;
/**
* @brief generate This method is generate a new key pair. Default implementation do nothing.
* @note Override this method for create of new class with new keys type.
* @param genesis This is genesis bytes Array. if is possible add support generate keys pair from genesis data.
* @return crypto pair keys.
*/
virtual CryptoPairKeys generate(const QByteArray& genesis = {}) const = 0;
};
}
#endif // CRYPTO_H

@ -1,5 +1,7 @@
#include "iparser.h"
#include <abstractdata.h>
namespace QH {
iParser::iParser() {
@ -19,4 +21,16 @@ QString iParser::pareseResultToString(const ParserResult &parseResult) const {
}
}
const QHash<unsigned short, std::function<PKG::AbstractData *()> > &
iParser::registeredTypes() const {
return _registeredTypes;
}
QSharedPointer<PKG::AbstractData> iParser::genPackage(unsigned short cmd) const {
return QSharedPointer<PKG::AbstractData>(_registeredTypes.value(cmd, [](){return nullptr;})());
}
bool iParser::checkCommand(unsigned short cmd) const {
return _registeredTypes.contains(cmd);
}
}

@ -39,6 +39,17 @@ class HEARTSHARED_EXPORT iParser
public:
iParser();
template<class T>
/**
* @brief registerPackageType This method register package type T.
* This is need to prepare pacakge for parsing in the parsePackage method.
*/
void registerPackageType() {
_registeredTypes[T::command()] = [](){
return new T();
};
};
/**
* @brief parsePackage This is main method of all childs classes of an AbstractNode class.
* This method work on own thread.
@ -153,6 +164,34 @@ public:
return QH::ParserResult::NotProcessed;
}
/**
* @brief registeredTypes This method return list of registered command.
* @return list of registered command.
* @see iParser::registerPackageType
*/
const QHash<unsigned short, std::function<PKG::AbstractData *()> > &registeredTypes() const;
/**
* @brief genPackage This is factory method that generate data pacakge objects by command.
* All object should be registered before using this method.
* @param cmd This is command of pacakge see Header::command.
* @return shared pointer to new data object.
* @see AbstractNode::registerPackageType
* @see Header::command
*/
QSharedPointer<PKG::AbstractData> genPackage(unsigned short cmd) const ;
/**
* @brief checkCommand This method check command are if registered type or not.
* @brief cmd This is command of a verifiable package.
* @return True if the package is registered in a node.
*/
bool checkCommand(unsigned short cmd) const;
private:
QHash<unsigned short, std::function<PKG::AbstractData*()>> _registeredTypes;
};

@ -1,391 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "cryptopairkeys.h"
#include "icrypto.h"
#include "keystorage.h"
#include <quasarapp.h>
#include <QCoreApplication>
#include <QDataStream>
#include <QDateTime>
#include <QDir>
#include <QFile>
#include <QMutex>
#include <QStandardPaths>
#include "config.h"
namespace QH {
#define THE_CLASS(x) QString::fromLatin1(typeid(*x).name())
#define VERSION_FILE "version"
KeyStorage::KeyStorage(ICrypto * cryptoMethod) {
_keyPoolSizeMutex = new QMutex();
_keysMutex = new QMutex();
_taskMutex = new QMutex();
_cryptoMethod = cryptoMethod;
assert(_cryptoMethod);
}
KeyStorage::~KeyStorage() {
stop();
waitForThreadFinished(WAIT_TIME);
if (!saveStorage()) {
QuasarAppUtils::Params::log("save keys to storae is failed!",
QuasarAppUtils::Error);
}
delete _keyPoolSizeMutex;
delete _keysMutex;
delete _taskMutex;
delete _cryptoMethod;
}
CryptoPairKeys KeyStorage::getNextPair(const QString &accsessKey,
const QByteArray& genesis,
int timeout) {
if (!isInited() && genesis == RAND_KEY) {
QuasarAppUtils::Params::log("You want get the random crypto keys pair in a not initialized crypto object.",
QuasarAppUtils::Error);
return CryptoPairKeys{};
}
if (_keyPoolSize <= 0) {
return CryptoPairKeys{};
}
if (!genKey(accsessKey, genesis)) {
return {};
}
start();
if (!waitForGeneratekey(accsessKey, timeout)) {
return CryptoPairKeys{};
}
QMutexLocker locker(_keysMutex);
return _keys.value(accsessKey, {});
}
int KeyStorage::getKeyPoolSize() const {
return _keyPoolSize;
}
void KeyStorage::setKeyPoolSize(int keyPoolSize) {
_keyPoolSizeMutex->lock();
_keyPoolSize = keyPoolSize;
_keyPoolSizeMutex->unlock();
start();
}
bool KeyStorage::isValid() const {
return isInited();
}
bool KeyStorage::isInited() const {
return _inited;
}
bool KeyStorage::crypt(QByteArray *data, const QByteArray &publicKey) {
return _cryptoMethod->crypt(data, publicKey);
}
bool KeyStorage::decrypt(QByteArray *cryptedData, const QByteArray &privateKey) {
return _cryptoMethod->decrypt(cryptedData, privateKey);
}
bool KeyStorage::sign(QByteArray *data, const QByteArray &privateKey) {
return _cryptoMethod->sign(data, privateKey);
}
QByteArray KeyStorage::extractSign(const QByteArray &data) {
return _cryptoMethod->extractSign(data);
}
QByteArray KeyStorage::concatSign(const QByteArray &data, const QByteArray &sign) {
return _cryptoMethod->concatSign(data, sign);
}
bool KeyStorage::check(const QByteArray &signedData, const QByteArray &publicKey) {
return _cryptoMethod->check(signedData, publicKey);
}
void KeyStorage::setGenesisList(const QList<QByteArray>& list) {
_keysMutex->lock();
for (const auto& i : list) {
_keys.insert(i, {});
}
_keysMutex->unlock();
start();
}
bool KeyStorage::toStorage(const QString &key) const {
if (!isValid())
return false;
_keysMutex->lock();
CryptoPairKeys value = _keys.value(key);
_keysMutex->unlock();
auto filePath = storageLocation() + "/" + key;
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
return false;
}
file.setPermissions(QFile::Permission::ReadOwner | QFile::Permission::WriteOwner);
QDataStream stream(&file);
stream << value;
file.close();
return true;
}
bool KeyStorage::fromStorage(const QByteArray &key) {
auto filePath = storageLocation() + "/" + key;
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly)) {
return false;
}
QDataStream stream(&file);
CryptoPairKeys value;
stream >> value;
file.close();
_keys.insert(key, value);
return value.isValid();
}
void KeyStorage::generateKeysByTasks() {
_taskMutex->lock();
auto tasks = _generateTasks;
_taskMutex->unlock();
for (auto it = tasks.begin(); it != tasks.end(); ++it) {
if (_stopGenerator) {
return;
}
const auto& value = _keys.value(it.key());
if (!value.isValid()) {
_keysMutex->lock();
if (it.value() == RAND_KEY && _randomKeysPool.size()) {
_keys[it.key()] = *_randomKeysPool.begin();
_randomKeysPool.erase(_randomKeysPool.begin());
} else {
_keys[it.key()] = _cryptoMethod->generate(it.value());
}
_keysMutex->unlock();
}
_taskMutex->lock();
_generateTasks.remove(it.key());
_taskMutex->unlock();
}
}
void KeyStorage::generateRandomKeys() {
_keyPoolSizeMutex->lock();
int size = _keyPoolSize;
_keyPoolSizeMutex->unlock();
while (size > _randomKeysPool.size()) {
if ((_stopGenerator))
return;
auto &&keys = _cryptoMethod->generate();
_keysMutex->lock();
_randomKeysPool.insert(keys);
_keysMutex->unlock();
}
}
void KeyStorage::run() {
if (_stopGenerator) {
return;
}
_keyPoolSizeMutex->lock();
int keyPoolSize = _keyPoolSize;
_keyPoolSizeMutex->unlock();
while ((_generateTasks.size() || keyPoolSize > _randomKeysPool.size())
&& !_stopGenerator) {
generateKeysByTasks();
generateRandomKeys();
_keyPoolSizeMutex->lock();
keyPoolSize = _keyPoolSize;
_keyPoolSizeMutex->unlock();
}
}
void KeyStorage::stop() {
_stopGenerator = true;
}
bool KeyStorage::waitForGeneratekey(const QString& key, int timeout) const {
return waitFor([this, &key](){return _keys.contains(key);}, timeout);
}
bool KeyStorage::waitForThreadFinished(int timeout) const {
return waitFor([this](){return !isRunning();}, timeout);
}
bool KeyStorage::waitFor(const std::function<bool()> &checkFunc, int timeout) const {
auto waitFor = timeout + QDateTime::currentMSecsSinceEpoch();
while (!checkFunc() && waitFor > QDateTime::currentMSecsSinceEpoch()) {
QCoreApplication::processEvents();
}
return checkFunc();
}
void KeyStorage::loadAllKeysFromStorage() {
auto list = QDir(storageLocation()).entryInfoList(QDir::Files | QDir::NoDotAndDotDot);
for (const auto& file: list ) {
if (file.fileName() != VERSION_FILE) {
fromStorage(file.fileName().toLatin1());
}
}
}
bool KeyStorage::saveStorage() const {
bool result = true;
for (auto it = _keys.begin(); it != _keys.end(); ++it) {
result = result && toStorage(it.key());
}
return result;
}
bool KeyStorage::genKey(const QString &accessKey, const QByteArray &genesis) {
if (accessKey.isEmpty())
return false;
QMutexLocker locker(_taskMutex);
_generateTasks.insert(accessKey, genesis);
return true;
}
QString KeyStorage::storageLocation() const {
return _storageLocation;
}
bool KeyStorage::initStorageLocation(const QString &value) {
QFile version(value + "/" + VERSION_FILE);
if (!QFile::exists(value)) {
if (!QDir().mkpath(value)) {
QuasarAppUtils::Params::log(" fail to create a key storagge. Into "
+ value, QuasarAppUtils::Error);
return false;
}
QFile::setPermissions(value,
QFile::Permission::ExeOwner |
QFile::Permission::ReadOwner |
QFile::Permission::WriteOwner);
QFile version(value + "/" + VERSION_FILE);
if (!version.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
return false;
}
QDataStream stream(&version);
stream << THE_CLASS(_cryptoMethod);
version.close();
} else {
if (!version.open(QIODevice::ReadOnly)) {
return false;
}
QDataStream stream(&version);
QString versionName;
stream >> versionName;
version.close();
if (THE_CLASS(_cryptoMethod) != versionName) {
return false;
}
}
_storageLocation = value;
return _storageLocation.size();
}
bool KeyStorage::initDefaultStorageLocation(const QString &dirName) {
auto storageLoation =
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) +
"/" + dirName;
if (dirName.isEmpty()) {
storageLoation += THE_CLASS(_cryptoMethod);
}
storageLoation += "/crypto/";
if (!initStorageLocation(storageLoation)) {
QuasarAppUtils::Params::log("CryptoStorage not inited",
QuasarAppUtils::Error);
return false;
}
loadAllKeysFromStorage();
return _inited = true;
}
void KeyStorage::clearStorage() const {
QDir::root().remove(storageLocation());
}
}

@ -1,266 +0,0 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef KEYSTORAGE_H
#define KEYSTORAGE_H
#include <QList>
#include <QThread>
#include "heart_global.h"
#include <QByteArray>
#include <QHash>
#include <QSet>
#include "config.h"
#define RAND_KEY ""
class QMutex;
namespace QH {
class CryptoPairKeys;
class ICrypto;
/**
* @brief The KeyStorage class provide the functionality of control crypto keys (generate, save and write).
* The current implementation of the key storage is collected cryptokeys like files in a key storage location.
*
* Work scheme:
*\image html KeyStorage.svg width=800px
*/
class HEARTSHARED_EXPORT KeyStorage: public QThread
{
Q_OBJECT
public:
/**
* @brief KeyStorage
* @param cryptoMethod This is pointer to any class inherited from ICrypto
*/
KeyStorage(ICrypto* cryptoMethod);
~KeyStorage();
/**
* @brief getNextPair This method take a one pair key from the keys pool or generate a new keys pair if the keys pool is empty.
* @warning If key pool is empty then this method frease a current thread for awaiting f neg generated pair key.
* @note if the key is not generated within the specified period of time, an invalid copy of the key pair will be returned.
* @param accsessKey The byte array for get a accesses to key from storage.
* @param genesis Set this params to empty for get random key pair or set the byte array for get a key pair for genesis array.
* @param timeout_msec This is timeout in milisecunds. default is WAIT_TIME (30000)
* @return pair of keys.
*/
CryptoPairKeys getNextPair(const QString &accsessKey,
const QByteArray &genesis = RAND_KEY,
int timeout_msec = WAIT_TIME);
/**
* @brief getKeyPoolSize - This method return size of keyPool.
* By default it is 1.
* @return value of keys pool size.
*/
int getKeyPoolSize() const;
/**
* @brief setKeyPoolSize This method return the size of keys pool.
* and start new work for generation a new keys.
* @param keyPoolSize This is a new size of pool.
*/
void setKeyPoolSize(int keyPoolSize);
/**
* @brief isValid This method check keysStorage to valid.
* @return true if the crypto object is valid.
*/
virtual bool isValid() const;
/**
* @brief isInited This method returns true if the crypto object was initialized correctly.
* @return true if the crypto object was initialized correctly.
*/
virtual bool isInited() const;
/**
* @brief crypt This method crypted a data message using a publicKey.
* @param data This is pointer to data array for crypting.
* @note data has ben changed after call this method.
* @param publicKey This is key for crypting data.
* @return true if function finished successful.
*/
bool crypt(QByteArray *data, const QByteArray& publicKey);
/**
* @brief decrypt This method decrypt a data message using a privateKey.
* @param cryptedData - Pointer to data array for decrypting.
* @note cryptedData Has been changed after call this method.
* @param privateKey This is private key for decrypting data.
* @return true if function finished successful.
*/
bool decrypt(QByteArray *cryptedData, const QByteArray& privateKey);
/**
* @brief sign This method sign a message using a privateKey.
* @param data This is pointer to data array for signed.
* @note data has been changed after call this method.
* @param privateKey This is key for signing a data message.
* @return true if function finished successful.
*/
bool sign(QByteArray* data, const QByteArray& privateKey);
/**
* @brief extractSign This method extract sign from signed byteArray.
* @param data This is a signed message.
* @return return array of sign.
*/
QByteArray extractSign(const QByteArray& data);
/**
* @brief concatSign This method concat a data of message and signs of a message.
* @param data This is message data.
* @param sign This is a sign of message.
* @return signed message.
*/
QByteArray concatSign(const QByteArray& data, const QByteArray& sign);
/**
* @brief check This method fore validation signed message.
* @param signedData This is signed message for checking.
* @param publicKey This is public key for validation of message.
* @return true if function finished successful and signedData is valid.
*/
bool check(const QByteArray& signedData, const QByteArray& publicKey);
/**
* @brief setGenesisList - set genesis list for generation key pairs.
* After invoke this method for each all items will be generated a keys pair.
*/
void setGenesisList(const QList<QByteArray> &list);
/**
* @brief storageLocation This method return a path of the storage location.
* By default storageLocation is QStandardPaths::DataLocation/KeysStorage
* @return path to storage location of crypto keys.
*/
QString storageLocation() const;
/**
* @brief initStorageLocation This method set a new path for storage location of keys.
* @param value This is a new path to storage location.
*/
bool initStorageLocation(const QString &value);
/**
* @brief initDefaultStorageLocation These is some as initStorageLocation,
* but set default path.
* @param dirName This is name of storage location. If This parametr weel be empty then
* storage location set default direction name. By default is name of crypto class.
* By default path of storage is:
* \code
* QStandardPaths::AppDataLocation/crypto/dirName;
* \endcode
* @return true if the storage inited successful.
*/
bool initDefaultStorageLocation(const QString& dirName = "");
/**
* @brief clearStorage - This method clear all storage.
*/
void clearStorage() const;
protected:
/**
* @brief toStorage This method save key into local storage.
* @param key This is key data value of keys pair.
* @note override this method if you want to change storage location or method of save of keys.
* @return true if key saved successful.
*/
virtual bool toStorage(const QString &key) const;
/**
* @brief fromStorage This method load keys from local storage.
* @param key This is key data value of keys pair.
* @return true if key pair saved successful.
*/
virtual bool fromStorage(const QByteArray& key);
/**
* @brief run This method start the key generator on own thread.
*/
void run() override;
/**
* @brief stop This method stop generate keys.
*/
void stop();
private:
/**
* @brief waitForGeneratekey.
* @param timeout - maximum time for generation new key. by default = WAIT_TIME (30000)
* @return true if key generated successful.
*/
bool waitForGeneratekey(const QString &key, int timeout = WAIT_TIME) const;
/**
* @brief waitForThreadFinished
* @param timeout
* @return
*/
bool waitForThreadFinished(int timeout = WAIT_TIME) const;
/**
* @brief waitFor - Base wait function.
* @param checkFunc - This is lambda of check event.
* @param timeout - Maximum time line of waiting of event.
* @return true if event is checkFunc return true.
*/
bool waitFor(const std::function<bool()>& checkFunc, int timeout) const;
/**
* @brief loadAllKeysFromStorage
*/
void loadAllKeysFromStorage();
/**
* @brief saveStorage This method for saved keys in storage.
* @return true if all keys has been saved in a storage.
*/
bool saveStorage() const;
/**
* @brief genKey - this method add a new task for generate keys pair
* @param accessKey - the byte array for get access of the keys pair.
* @param genesis - The byte array for generate new key.
* @note If access key well be empty then this method return false.
* @note For generate random key use a RAND_KEY genesis or empty value.
* @return true if task of generation a new pair keys added successful else false.
*/
bool genKey(const QString &accessKey, const QByteArray& genesis = RAND_KEY);
QHash<QString, CryptoPairKeys> _keys;
QSet<CryptoPairKeys> _randomKeysPool;
QHash<QString, QByteArray> _generateTasks;
int _keyPoolSize = 1;
QMutex *_keyPoolSizeMutex = nullptr;
QMutex *_keysMutex = nullptr;
QMutex *_taskMutex = nullptr;
QString _storageLocation;
bool _inited = false;
bool _stopGenerator = false;
ICrypto *_cryptoMethod = nullptr;
void generateKeysByTasks();
void generateRandomKeys();
};
}
#endif // KEYSTORAGE_H

@ -9,7 +9,6 @@
#include <QDataStream>
#include <QMap>
#include <typeinfo>
#include "heart.h"
#include <limits>
#include <quasarapp.h>
#include <QCryptographicHash>
@ -44,17 +43,9 @@ bool AbstractData::toPackage(Package &package,
return package.isValid();
}
QDataStream &AbstractData::fromStream(QDataStream &stream) {
return stream;
}
QDataStream &AbstractData::toStream(QDataStream &stream) const {
return stream;
}
bool AbstractData::checkCmd() const {
unsigned int code = typeid (*this).hash_code();
return code == localCode(); \
return code == localCode();
}
bool AbstractData::isValid() const {

@ -7,6 +7,7 @@
#ifndef ABSTRACTDATA_H
#define ABSTRACTDATA_H
#include "humanreadableobject.h"
#include "package.h"
#include <streambase.h>
@ -49,12 +50,10 @@ public:
protected:
// StreamBase interface override this methods for serialization your package
QDataStream &fromStream(QDataStream &stream) {
AbstractData::fromStream(stream);
stream >> _data;
return stream;
}
QDataStream &toStream(QDataStream &stream) const {
AbstractData::toStream(stream);
stream << _data;
return stream;
}
@ -122,11 +121,11 @@ protected:
* If the implementation of this method differs from the example, the data will not be copied correctly.
* @see AbstractNode
*/
class HEARTSHARED_EXPORT AbstractData : public StreamBase
class HEARTSHARED_EXPORT AbstractData : public StreamBase, public QuasarAppUtils::iHRO
{
public:
virtual ~AbstractData() override;
~AbstractData() override;
/**
* @brief cmd - This is command of this object, (for generate cmd use macross QH_PACKAGE)
@ -184,7 +183,7 @@ public:
* @brief toString - Return a string implementation for this object.
* @return String of object.
*/
virtual QString toString() const;
QString toString() const override;
/**
* @brief create - This is factory method for create a new object.
@ -229,9 +228,6 @@ protected:
*/
virtual unsigned int localCode() const = 0;
QDataStream& fromStream(QDataStream& stream) override;
QDataStream& toStream(QDataStream& stream) const override;
private:
/**
* @brief checkCmd This method check QH_PACKAGE macross.

@ -28,7 +28,6 @@ BadRequest::BadRequest(const Package &package):
}
QDataStream &BadRequest::fromStream(QDataStream &stream) {
AbstractData::fromStream(stream);
stream >> _errCode;
stream >> _err;
@ -37,7 +36,6 @@ QDataStream &BadRequest::fromStream(QDataStream &stream) {
}
QDataStream &BadRequest::toStream(QDataStream &stream) const {
AbstractData::toStream(stream);
stream << _errCode;
stream << _err;

@ -25,16 +25,12 @@ void BigDataBase::setPackageId(int newPackageId) {
}
QDataStream &BigDataBase::fromStream(QDataStream &stream) {
AbstractData::fromStream(stream);
stream >> _packageId;
return stream;
}
QDataStream &BigDataBase::toStream(QDataStream &stream) const {
AbstractData::toStream(stream);
stream << _packageId;
return stream;

@ -14,5 +14,13 @@ namespace PKG {
CloseConnection::CloseConnection() {
}
QDataStream &CloseConnection::fromStream(QDataStream &stream) {
return stream;
}
QDataStream &CloseConnection::toStream(QDataStream &stream) const {
return stream;
}
}
}

@ -31,6 +31,11 @@ class HEARTSHARED_EXPORT CloseConnection: public AbstractData
public:
CloseConnection();
// StreamBase interface
protected:
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
};
}
}

@ -53,8 +53,23 @@ public:
_packData.push_back(data);
};
/**
* @brief isValid This implementation check all items of the pack to valid and packa size. The pack size should be more then 0.
* @return true if the pack of items is valid else flase..
*/
bool isValid() const override {
return AbstractData::isValid() && _packData.size();
if (!_packData.size()) {
return false;
}
for (const auto& it: _packData) {
if (!it->isValid()) {
return false;
}
}
return AbstractData::isValid();
};
/**
@ -77,7 +92,6 @@ public:
protected:
QDataStream &fromStream(QDataStream &stream) override {
AbstractData::fromStream(stream);
int size = 0;
stream >> size;
@ -95,7 +109,6 @@ protected:
};
QDataStream &toStream(QDataStream &stream) const override {
AbstractData::toStream(stream);
stream << static_cast<int>(_packData.size());
for (const auto &ptr: qAsConst(_packData)) {

@ -33,14 +33,12 @@ void Ping::setAnsver(bool ansver) {
}
QDataStream &Ping::fromStream(QDataStream &stream) {
AbstractData::fromStream(stream);
stream >> _ansver;
return stream;
}
QDataStream &Ping::toStream(QDataStream &stream) const {
AbstractData::toStream(stream);
stream << _ansver;
return stream;
}

@ -5,7 +5,6 @@
* of this license document, but changing it is not allowed.
*/
#include "package.h"
#include "streambase.h"
#include <QDataStream>
@ -35,6 +34,18 @@ QByteArray StreamBase::toBytes() const {
return res;
}
bool StreamBase::fromBase64(const QString &data) {
return fromBase64(data.toLatin1());
}
bool StreamBase::fromBase64(const QByteArray &data) {
return fromBytes(QByteArray::fromBase64(data, QByteArray::Base64UrlEncoding));
}
QByteArray StreamBase::toBase64() const {
return toBytes().toBase64(QByteArray::Base64UrlEncoding);
}
unsigned int StreamBase::typeId() const {
return typeid (*this).hash_code();
}

@ -42,6 +42,26 @@ public:
*/
QByteArray toBytes() const;
/**
* @brief fromBase64 This method provide initialization of object from the base64 string.
* @param data This is input base64 data.
* @note converting from the QString is slowly instand of QByteArray, so use the StreamBase::fromBase64(const QByteArray &data) method.
* @return true if all good else false.
*/
bool fromBase64(const QString &data);
/**
* @brief fromBase64 This method provide initialization of object from the base64 string.
* @param data This is input base64 data.
* @return true if all good else false.
*/
bool fromBase64(const QByteArray &data);
/**
* @brief toBase64 This method convert a current object to the base64 string.
* @return base64 string of this object.
*/
QByteArray toBase64() const;
/**
* @brief This is wrapper over toStream.

@ -36,6 +36,8 @@ if (${HEART_BUILD_LVL} GREATER_EQUAL 0)
"AbstractSpace/*.cpp" "AbstractSpace/*.h" "AbstractSpace/*.qrc"
"AbstractSpace/packages/*.cpp" "AbstractSpace/packages/*.h" "AbstractSpace/packages/*.qrc"
"AbstractSpace/Private/*.cpp" "AbstractSpace/Private/*.h" "AbstractSpace/Private/*.qrc"
"AbstractSpace/hcrypto/*.cpp" "AbstractSpace/hcrypto/*.h" "AbstractSpace/hcrypto/*.qrc"
"AbstractSpace/hcryptoFeatures/*.cpp" "AbstractSpace/hcryptoFeatures/*.h" "AbstractSpace/hcryptoFeatures/*.qrc"
)

@ -40,12 +40,11 @@ bool BaseNodeInfo::confirmData() const {
return AbstractNodeInfo::confirmData();
}
const QVariant& BaseNodeInfo::id() const {
const QString& BaseNodeInfo::id() const {
return _id;
}
void BaseNodeInfo::setId(const QVariant &id)
{
void BaseNodeInfo::setId(const QString &id) {
_id = id;
}

@ -56,17 +56,17 @@ public:
* @brief id This method return id of the connected user.
* @return User id.
*/
const QVariant &id() const;
const QString &id() const;
/**
* @brief setId This method set userId for connected object.
* @param id This is new value of user id.
*/
void setId(const QVariant &id);
void setId(const QString &id);
protected:
AccessToken _token;
QVariant _id;
QString _id;
};

@ -25,6 +25,7 @@
#include <sqldb.h>
#include "getsinglevalue.h"
#include "setsinglevalue.h"
#include <qaglobalutils.h>
namespace QH {
using namespace PKG;
@ -135,7 +136,7 @@ bool DataBase::welcomeAddress(AbstractNodeInfo *) {
return true;
}
bool DataBase::isBanned(const QVariant &node) const {
bool DataBase::isBanned(const QString &node) const {
NetworkMember member(node);
auto objectFromDataBase = db()->getObject<AbstractNetworkMember>(member);
@ -163,8 +164,22 @@ void DataBase::objectChanged(const QSharedPointer<DBObject> &) {
}
DBPatchMap DataBase::dbPatches() const {
return {};
const DBPatchMap DataBase::dbPatches() const {
return _dbPatches;
}
void DataBase::addDBPatch(const DBPatch &patch) {
debug_assert(patch.isValid(),
"Failed to initialise a Data base patch!"
" Patch object is invalid");
debug_assert(!_dbPatches[patch.versionFrom].contains(patch.versionTo),
"Failed to initialise a Data base patch!");
_dbPatches[patch.versionFrom][patch.versionTo] = patch;
_targetDBVersion = std::max(_targetDBVersion, patch.versionTo);
}
void DataBase::memberSubsribed(const QVariant &, unsigned int ) {
@ -183,7 +198,7 @@ QString DataBase::dbLocation() const {
return "";
}
bool DataBase::changeTrust(const QVariant &id, int diff) {
bool DataBase::changeTrust(const QString &id, int diff) {
if (!_db)
return false;
@ -210,13 +225,16 @@ bool DataBase::isForbidenTable(const QString &table) {
}
bool DataBase::upgradeDataBase() {
auto patches = dbPatches();
int actyalyVersion = patches.size();
int currentVersion = 0;
if (!db())
return false;
DBPatchMap patchesPack = dbPatches();
if (!patchesPack.size()) {
return true;
}
int currentVersion = 0;
bool fsupportUpgrade = db()->doQuery("SELECT COUNT(*) FROM DataBaseAttributes", true);
if (!fsupportUpgrade) {
@ -232,31 +250,39 @@ bool DataBase::upgradeDataBase() {
if (auto responce = _db->getObject(request)) {
currentVersion = responce->value().toInt();
}
}
bool fUpdated = false;
while (currentVersion < actyalyVersion) {
if (currentVersion < _targetDBVersion)
onBeforeDBUpgrade(currentVersion, _targetDBVersion);
auto patch = patches.value(currentVersion, {});
while (currentVersion < _targetDBVersion) {
QString message;
message = "Upgrade data base!. to %0 versions";
message = "Upgrade data base from %0 to %1 versions. %2";
message = message.arg(currentVersion);
QuasarAppUtils::Params::log(message,
QuasarAppUtils::Info);
auto patches = patchesPack.value(currentVersion, {});
if (patch && !patch(db())) {
QuasarAppUtils::Params::log("Failed to " + message,
if (!patches.size()) {
QuasarAppUtils::Params::log("Failed to " + message.arg("Unknown", "Required patch not found!"),
QuasarAppUtils::Error);
return false;
}
currentVersion++;
fUpdated = true;
}
auto patch = patches.last();
message = message.arg(patch.versionTo);
QuasarAppUtils::Params::log(message.arg("(Begin)"),
QuasarAppUtils::Info);
if (!patch.action(db())) {
QuasarAppUtils::Params::log("Failed to " + message.arg("Patch finished with error code!"),
QuasarAppUtils::Error);
return false;
}
currentVersion = patch.versionTo;
if (fUpdated) {
auto updateVersionRequest = QSharedPointer<PKG::SetSingleValue>::create(
DbAddress{"DataBaseAttributes", "version"},
"value", currentVersion, "name");
@ -271,6 +297,8 @@ bool DataBase::upgradeDataBase() {
return true;
}
void DataBase::onBeforeDBUpgrade(int , int ) const { }
const QString &DataBase::localNodeName() const {
return _localNodeName;
}
@ -288,7 +316,7 @@ QVariantMap DataBase::defaultDbParams() const {
}
DBOperationResult
QH::DataBase::getObject(const QVariant &requester,
QH::DataBase::getObject(const QString &requester,
const QH::DBObject &templateObj,
QSharedPointer<QH::PKG::DBObject> &result) const {
@ -312,7 +340,7 @@ QH::DataBase::getObject(const QVariant &requester,
}
DBOperationResult
DataBase::getObjects(const QVariant &requester,
DataBase::getObjects(const QString &requester,
const DBObject &templateObj,
QList<QSharedPointer<DBObject>> &result) const {
if (!_db) {
@ -338,7 +366,7 @@ DataBase::getObjects(const QVariant &requester,
}
DBOperationResult
DataBase::updateObject(const QVariant &requester,
DataBase::updateObject(const QString &requester,
const QSharedPointer<DBObject> &saveObject) {
if (!_db) {
@ -360,14 +388,14 @@ DataBase::updateObject(const QVariant &requester,
}
DBOperationResult
DataBase::createObject(const QVariant &requester,
DataBase::createObject(const QString &requester,
const QSharedPointer<DBObject> &obj) {
if (!_db) {
return DBOperationResult::Unknown;
}
if (isForbidenTable(obj->tableName())) {
if (isForbidenTable(obj->table())) {
return DBOperationResult::Forbidden;
}
@ -387,7 +415,7 @@ DataBase::createObject(const QVariant &requester,
}
DBOperationResult
DataBase::updateIfNotExistsCreateObject(const QVariant &requester,
DataBase::updateIfNotExistsCreateObject(const QString &requester,
const QSharedPointer<DBObject> &obj) {
auto opResult = updateObject(requester, obj);
@ -399,7 +427,7 @@ DataBase::updateIfNotExistsCreateObject(const QVariant &requester,
}
DBOperationResult
DataBase::changeObjects(const QVariant &requester,
DataBase::changeObjects(const QString &requester,
const DBObject &templateObj,
const std::function<bool (const QSharedPointer<DBObject> &)> &changeAction) {
@ -438,11 +466,11 @@ QVariant DataBase::getSender(const AbstractNodeInfo *connectInfo,
}
DBOperationResult
DataBase::checkPermission(const QVariant &requester,
DataBase::checkPermission(const QString &requester,
const DbAddress &objectAddress,
const Permission& requarimentPermision) const {
if (!requester.isValid())
if (!requester.isEmpty())
return DBOperationResult::Unknown;
if (!_db) {
@ -518,7 +546,7 @@ bool DataBase::removePermission(const QVariant &member,
}
DBOperationResult
DataBase::deleteObject(const QVariant &requester,
DataBase::deleteObject(const QString &requester,
const QSharedPointer<DBObject> &dbObject) {
if (!_db) {

@ -8,7 +8,7 @@
#ifndef QH_DATABASE_H
#define QH_DATABASE_H
#include "abstractnode.h"
#include "dbpatch.h"
#include <dbobject.h>
#include <hostaddress.h>
#include <permission.h>
@ -27,20 +27,7 @@ class SqlDBWriter;
class DbAddress;
class NodeId;
class iObjectProvider;
/**
* @brief DBPatch This is function that should be upgrade database.
* @see DBPatchMap
* @see DataBaseNode::dbPatch
*/
typedef std::function<bool (const QH::iObjectProvider *)> DBPatch;
/**
* @brief DBPatchMap This is list when index of list is version of database and value if function that should be upgrade database.
* @see DataBaseNode::dbPatch
* @see DBPatchMap
*/
typedef QList<DBPatch> DBPatchMap;
class AbstractNodeInfo;
/**
* @brief The DataBase class is DataBase base implementation.
@ -111,7 +98,7 @@ public:
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult deleteObject(const QVariant &requester,
DBOperationResult deleteObject(const QString &requester,
const QSharedPointer<PKG::DBObject> &dbObject);
/**
@ -123,7 +110,7 @@ public:
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult getObject(const QVariant &requester,
DBOperationResult getObject(const QString &requester,
const PKG::DBObject &templateObj,
QSharedPointer<PKG::DBObject> &result) const;
@ -136,7 +123,7 @@ public:
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult getObjects(const QVariant &requester,
DBOperationResult getObjects(const QString &requester,
const PKG::DBObject &templateObj,
QList<QSharedPointer<PKG::DBObject>> &result) const;
@ -148,7 +135,7 @@ public:
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult updateObject(const QVariant &requester,
DBOperationResult updateObject(const QString &requester,
const QSharedPointer<PKG::DBObject> &saveObject);
/**
@ -159,7 +146,7 @@ public:
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult createObject(const QVariant &requester,
DBOperationResult createObject(const QString &requester,
const QSharedPointer<PKG::DBObject> &obj);
/**
@ -172,7 +159,7 @@ public:
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult updateIfNotExistsCreateObject(const QVariant &requester,
DBOperationResult updateIfNotExistsCreateObject(const QString &requester,
const QSharedPointer<PKG::DBObject> &obj);
/**
@ -185,7 +172,7 @@ public:
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult changeObjects(const QVariant &requester,
DBOperationResult changeObjects(const QString &requester,
const PKG::DBObject &templateObj,
const std::function<bool (const QSharedPointer<QH::PKG::DBObject>&)> &changeAction);
@ -194,7 +181,7 @@ public:
* @param member This is member of network (node, client or server).
* @return true if node is banned.
*/
bool isBanned(const QVariant &member) const;
bool isBanned(const QString &member) const;
/**
* @brief dbLocation This method return location of nodes or clients database.
@ -209,7 +196,7 @@ public:
* @param diff This is difference of trust.
* @return true if trust of user changed successful.
*/
bool changeTrust(const QVariant &id, int diff);
bool changeTrust(const QString &id, int diff);
signals:
@ -296,7 +283,7 @@ protected:
* @return DBOperationResult::Alowed if permission granted.
* For more information about result see the DBOperationResult enum.
*/
virtual DBOperationResult checkPermission(const QVariant &requester,
virtual DBOperationResult checkPermission(const QString &requester,
const DbAddress& objectAddress,
const Permission& requarimentPermision) const;
@ -402,31 +389,48 @@ protected:
* Where the 0 version is first version of database. (genesis)
*
* @code{cpp}
* QH::DBPatchMap dbPatches() const {
QH::DBPatchMap result;
addDBPatch({
0, // fromVersion
1, // toVersion
[](const QH::iObjectProvider* database) -> bool {
// Some code for update from 0 to 1
} // action of patch
});
result += [](const QH::iObjectProvider* database) -> bool {
// Some code for update from 0 to 1
};
addDBPatch({
1, // fromVersion
2, // toVersion
[](const QH::iObjectProvider* database) -> bool {
// Some code for update from 1 to 2
} // action of patch
});
result += [](const QH::iObjectProvider* database) -> bool {
// Some code for update from 1 to 2
};
result += [](const QH::iObjectProvider* database) -> bool {
// Some code for update from 2 to 3
};
return result;
}
addDBPatch({
2, // fromVersion
3, // toVersion
[](const QH::iObjectProvider* database) -> bool {
// Some code for update from 2 to 3
} // action of patch
});
* @endcode
*
* @return Map of database pactches.
*
* @see DBPatchMap
* @see DBPatch
* @see DataBase::addDBPatch
* @see DataBase::onBeforeDBUpgrade
*/
virtual DBPatchMap dbPatches() const;
virtual const DBPatchMap dbPatches() const;
/**
* @brief addDBPatch This method add database patch to the data base object.
* @param patch This is object of the database patch
* @note This method will be crashed if patch is invalid.
* @see DataBase::dbPatches
* @see DataBase::onBeforeDBUpgrade
*/
void addDBPatch(const DBPatch& patch);
/**
* @brief upgradeDataBase This method upgrade data base to actyaly database version.
@ -435,6 +439,15 @@ protected:
* @note if you want to disable this feature then override this method and return true.
*/
virtual bool upgradeDataBase();
/**
* @brief onBeforeDBUpgrade This method will be invoked before upgrade database.
* @param currentVerion This is current database version
* @param tergetVersion This is target database version.
* @see DataBase::dbPatches
* @see DataBase::addDBPatch
*/
virtual void onBeforeDBUpgrade(int currentVerion, int tergetVersion) const;
private:
/**
* @brief workWithSubscribe This method work with subscribe commnads.
@ -450,6 +463,8 @@ private:
bool isForbidenTable(const QString& table);
ISqlDBCache *_db = nullptr;
unsigned short _targetDBVersion = 0;
DBPatchMap _dbPatches;
QString _localNodeName;
friend class DataBaseNode;

@ -20,7 +20,6 @@
#include <websocketcontroller.h>
#include <QCoreApplication>
#include <ping.h>
#include <keystorage.h>
#include <basenodeinfo.h>
#include <abstractnetworkmember.h>
#include <memberpermisionobject.h>
@ -89,7 +88,7 @@ bool DataBaseNode::isSqlInited() const {
return _db && _db->isSqlInited();
}
DBOperationResult DataBaseNode::checkPermission(const QVariant &requester,
DBOperationResult DataBaseNode::checkPermission(const QString &requester,
const DbAddress &objectAddress,
const Permission &requarimentPermision) const {
if (!_db) {
@ -126,10 +125,14 @@ bool DataBaseNode::welcomeAddress(AbstractNodeInfo *) {
return true;
}
bool DataBaseNode::isBanned(const QVariant &node) const {
bool DataBaseNode::isBanned(const QString &node) const {
return db()->isBanned(node);
}
bool DataBaseNode::isBanned(const AbstractNodeInfo *node) const {
return AbstractNode::isBanned(node);
}
bool DataBaseNode::notifyObjectChanged(const QSharedPointer<PKG::ISubscribableData> &item) {
if (!item.dynamicCast<PKG::AbstractData>()) {
@ -199,13 +202,13 @@ bool DataBaseNode::changeTrust(const HostAddress &id, int diff) {
if (!info)
return false;
if (info->id().isValid())
if (info->id().size())
return changeTrust(info->id(), diff);
return AbstractNode::changeTrust(id, diff);
}
bool DataBaseNode::changeTrust(const QVariant &id, int diff) {
bool DataBaseNode::changeTrust(const QString &id, int diff) {
if (!_db)
return false;
return _db->changeTrust(id, diff);
@ -250,7 +253,7 @@ ParserResult DataBaseNode::parsePackage(const QSharedPointer<AbstractData> &pkg,
if (WebSocket::command() == pkg->cmd()) {
WebSocket *obj = static_cast<WebSocket*>(pkg.data());
QVariant requesterId = getSender(sender, obj);
auto requesterId = getSender(sender, obj);
if (!obj->isValid()) {
badRequest(sender->networkAddress(), pkgHeader,
{
@ -289,7 +292,7 @@ DataBase *DataBaseNode::db() const {
}
bool DataBaseNode::workWithSubscribe(const WebSocket &rec,
const QVariant &clientOrNodeid,
const QString &clientOrNodeid,
const AbstractNodeInfo * sender) {
auto _db = db();
@ -325,7 +328,7 @@ bool DataBaseNode::workWithSubscribe(const WebSocket &rec,
}
DBOperationResult
QH::DataBaseNode::getObject(const QVariant &requester,
QH::DataBaseNode::getObject(const QString &requester,
const QH::DBObject &templateObj,
QSharedPointer<QH::PKG::DBObject> &result) const {
@ -336,7 +339,7 @@ QH::DataBaseNode::getObject(const QVariant &requester,
}
DBOperationResult
DataBaseNode::getObjects(const QVariant &requester,
DataBaseNode::getObjects(const QString &requester,
const DBObject &templateObj,
QList<QSharedPointer<DBObject>> &result) const {
@ -347,7 +350,7 @@ DataBaseNode::getObjects(const QVariant &requester,
}
DBOperationResult
DataBaseNode::updateObject(const QVariant &requester,
DataBaseNode::updateObject(const QString &requester,
const QSharedPointer<DBObject> &saveObject) {
if (!_db) {
@ -357,7 +360,7 @@ DataBaseNode::updateObject(const QVariant &requester,
}
DBOperationResult
DataBaseNode::createObject(const QVariant &requester,
DataBaseNode::createObject(const QString &requester,
const QSharedPointer<DBObject> &obj) {
if (!_db) {
@ -367,7 +370,7 @@ DataBaseNode::createObject(const QVariant &requester,
}
DBOperationResult
DataBaseNode::updateIfNotExistsCreateObject(const QVariant &requester,
DataBaseNode::updateIfNotExistsCreateObject(const QString &requester,
const QSharedPointer<DBObject> &obj) {
if (!_db) {
@ -377,7 +380,7 @@ DataBaseNode::updateIfNotExistsCreateObject(const QVariant &requester,
}
DBOperationResult
DataBaseNode::changeObjects(const QVariant &requester,
DataBaseNode::changeObjects(const QString &requester,
const DBObject &templateObj,
const std::function<bool (const QSharedPointer<DBObject> &)> &changeAction) {
@ -387,7 +390,7 @@ DataBaseNode::changeObjects(const QVariant &requester,
return _db->changeObjects(requester, templateObj, changeAction);
}
QVariant DataBaseNode::getSender(const AbstractNodeInfo *connectInfo,
QString DataBaseNode::getSender(const AbstractNodeInfo *connectInfo,
const AbstractData *) const {
auto info = dynamic_cast<const BaseNodeInfo*>(connectInfo);
@ -398,7 +401,7 @@ QVariant DataBaseNode::getSender(const AbstractNodeInfo *connectInfo,
}
DBOperationResult
DataBaseNode::deleteObject(const QVariant &requester,
DataBaseNode::deleteObject(const QString &requester,
const QSharedPointer<DBObject> &dbObject) {
if (!_db) {

@ -86,7 +86,7 @@ public:
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult deleteObject(const QVariant &requester,
DBOperationResult deleteObject(const QString &requester,
const QSharedPointer<PKG::DBObject> &dbObject);
/**
@ -98,7 +98,7 @@ public:
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult getObject(const QVariant &requester,
DBOperationResult getObject(const QString &requester,
const PKG::DBObject &templateObj,
QSharedPointer<PKG::DBObject> &result) const;
@ -111,7 +111,7 @@ public:
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult getObjects(const QVariant &requester,
DBOperationResult getObjects(const QString &requester,
const PKG::DBObject &templateObj,
QList<QSharedPointer<PKG::DBObject>> &result) const;
@ -123,7 +123,7 @@ public:
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult updateObject(const QVariant &requester,
DBOperationResult updateObject(const QString &requester,
const QSharedPointer<PKG::DBObject> &saveObject);
/**
@ -134,7 +134,7 @@ public:
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult createObject(const QVariant &requester,
DBOperationResult createObject(const QString &requester,
const QSharedPointer<PKG::DBObject> &obj);
/**
@ -147,7 +147,7 @@ public:
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult updateIfNotExistsCreateObject(const QVariant &requester,
DBOperationResult updateIfNotExistsCreateObject(const QString &requester,
const QSharedPointer<PKG::DBObject> &obj);
/**
@ -160,7 +160,7 @@ public:
* @return result of operation (allow, forbidden, unknown).
* For more information about results see the DBOperationResult enum.
*/
DBOperationResult changeObjects(const QVariant &requester,
DBOperationResult changeObjects(const QString &requester,
const PKG::DBObject &templateObj,
const std::function<bool (const QSharedPointer<QH::PKG::DBObject>&)> &changeAction);
@ -179,7 +179,7 @@ public:
* @return DBOperationResult::Alowed if permission granted.
* For more information about result see the DBOperationResult enum.
*/
DBOperationResult checkPermission(const QVariant &requester,
DBOperationResult checkPermission(const QString &requester,
const DbAddress& objectAddress,
const Permission& requarimentPermision) const;
@ -208,7 +208,7 @@ protected:
* @param diff This is difference of trust.
* @return true if trust of user changed successful.
*/
virtual bool changeTrust(const QVariant &id, int diff);
virtual bool changeTrust(const QString &id, int diff);
/**
* @brief hashgenerator This method generate a hash from any value.
@ -249,7 +249,7 @@ protected:
* @param requestData This is data of request.
* @return id of requester member.
*/
virtual QVariant getSender(const AbstractNodeInfo *connectInfo, const PKG::AbstractData *requestData) const;
virtual QString getSender(const AbstractNodeInfo *connectInfo, const PKG::AbstractData *requestData) const;
/**
* @brief dbLocation This method return location of nodes or clients database.
@ -270,7 +270,9 @@ protected:
* @param member This is member of network (node, client or server).
* @return true if node is banned.
*/
bool isBanned(const QVariant &member) const;
bool isBanned(const QString &member) const;
bool isBanned(const AbstractNodeInfo *member) const override;
/**
* @brief notifyObjectChanged This method send all subscriptions message with this object.
@ -312,7 +314,7 @@ private:
* @return true if data parsed successful.
*/
bool workWithSubscribe(const PKG::WebSocket &rec,
const QVariant &clientOrNodeid,
const QString &clientOrNodeid,
const AbstractNodeInfo *sender);

@ -0,0 +1,16 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#include "dbpatch.h"
namespace QH {
bool DBPatch::isValid() const {
return versionFrom < versionTo && action;
}
}

@ -0,0 +1,51 @@
/*
* Copyright (C) 2018-2022 QuasarApp.
* Distributed under the lgplv3 software license, see the accompanying
* Everyone is permitted to copy and distribute verbatim copies
* of this license document, but changing it is not allowed.
*/
#ifndef DBPATCH_H
#define DBPATCH_H
#include "iobjectprovider.h"
namespace QH {
/**
* @brief DBPatch This is function that should be upgrade database.
* @see DBPatchMap
* @see DataBaseNode::dbPatch
*
* @note version is version number of the current database.
* After execute this path version of data base will be increment.
*/
struct DBPatch {
/// This is version of data base that need to up.
/// For example - we has a data base with version 1 and we want to upgrade to version 2 then you need to set cersion field version to 1.
unsigned short versionFrom = 0;
/// This is version of data base that need to up.
/// For example - we has a data base with version 1 and we want to upgrade to version 2 then you need to set cersion field version to 1.
unsigned short versionTo = 0;
/// This is lymbda function with action that will upgrade data base to new versio.
std::function<bool (const QH::iObjectProvider *)> action;
/**
* @brief isValid This method check this oject to valid.
* @return true if object is valid else false.
*/
bool isValid() const;
};
/**
* @brief DBPatchMap This is 2 depch map of the DBPatch structure when the first key it is version (from) and second key is version to.
* @see DataBaseNode::dbPatch
* @see DBPatchMap
*/
typedef QMap<unsigned short, QMap<unsigned short, DBPatch>> DBPatchMap;
}
#endif // DBPATCH_H

@ -16,7 +16,7 @@
namespace QH {
namespace PKG {
AbstractNetworkMember::AbstractNetworkMember():DBObject("NetworkMembers") {
AbstractNetworkMember::AbstractNetworkMember() {
}
@ -25,16 +25,14 @@ AbstractNetworkMember::AbstractNetworkMember(const Package &pkg):
fromBytes(pkg.data);
}
AbstractNetworkMember::AbstractNetworkMember(const QVariant &id):
AbstractNetworkMember::AbstractNetworkMember(const QString& id):
AbstractNetworkMember() {
setId(id);
}
bool AbstractNetworkMember::fromSqlRecord(const QSqlRecord &q) {
if (!DBObject::fromSqlRecord(q)) {
return false;
}
setId(q.value("id").toString());
setAuthenticationData(q.value("authenticationData").toByteArray());
setTrust(q.value("trust").toInt());
@ -52,6 +50,7 @@ void AbstractNetworkMember::setAuthenticationData(const QByteArray &publickKey)
QDataStream &AbstractNetworkMember::fromStream(QDataStream &stream) {
DBObject::fromStream(stream);
stream >> _id;
stream >> _authenticationData;
stream >> _trust;
@ -59,8 +58,7 @@ QDataStream &AbstractNetworkMember::fromStream(QDataStream &stream) {
}
QDataStream &AbstractNetworkMember::toStream(QDataStream &stream) const {
DBObject::toStream(stream);
stream << _id;
stream << _authenticationData;
stream << _trust;
return stream;
@ -68,17 +66,33 @@ QDataStream &AbstractNetworkMember::toStream(QDataStream &stream) const {
DBVariantMap AbstractNetworkMember::variantMap() const {
auto map = DBObject::variantMap();
map["authenticationData"] = {_authenticationData, MemberType::InsertUpdate};
map["trust"] = {_trust, MemberType::InsertUpdate};
return {{"id", {_id, QH::PKG::MemberType::PrimaryKey}},
{"authenticationData", {_authenticationData, QH::PKG::MemberType::InsertUpdate}},
{"trust", {_trust, QH::PKG::MemberType::InsertUpdate}},
return map;
};
}
QString AbstractNetworkMember::primaryKey() const {
return "id";
}
QString AbstractNetworkMember::primaryValue() const {
return _id;
}
const QString &AbstractNetworkMember::getId() const {
return _id;
}
void AbstractNetworkMember::setId(const QString &newId) {
_id = newId;
}
QString AbstractNetworkMember::table() const {
return "NetworkMembers";
}
int AbstractNetworkMember::trust() const {
return _trust;
}
@ -103,6 +117,7 @@ bool AbstractNetworkMember::copyFrom(const AbstractData * other) {
if (!otherObject)
return false;
this->_id = otherObject->_id;
this->_authenticationData = otherObject->_authenticationData;
this->_trust = otherObject->_trust;

@ -26,7 +26,7 @@ class HEARTSHARED_EXPORT AbstractNetworkMember: public DBObject
public:
AbstractNetworkMember();
AbstractNetworkMember(const Package& pkg);
AbstractNetworkMember(const QVariant &id);
AbstractNetworkMember(const QString &id);
// DBObject interface
bool fromSqlRecord(const QSqlRecord &q) override;
@ -67,15 +67,29 @@ public:
*/
void setTrust(int trust);
/**
* @brief getId This method return id of this object in database.
* @return id of this object in database.
*/
const QString &getId() const;
/**
* @brief setId This method sets new id of this object.
* @param newId This is new value of @a id of this object.
*/
void setId(const QString &newId);
QString table() const override;
protected:
// StreamBase interface
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
QString primaryKey() const override;
QString primaryValue() const override;
private:
QString _id;
QByteArray _authenticationData;
int _trust;

@ -21,30 +21,21 @@
namespace QH {
namespace PKG {
DBObject::DBObject(const QString &tableName) {
DBObject::DBObject() {
DBObject::clear();
_dbId.setTable(tableName);
}
DBObject::DBObject(const DbAddress &address) {
_dbId = address;
}
DBObject::~DBObject() {
}
QString DBObject::tableName() const {
return _dbId.table();
}
PrepareResult DBObject::prepareSelectQuery(QSqlQuery &q) const {
auto map = variantMap().keys();
QString queryString = "SELECT " + map.join(",") + " FROM %0 " + getWhereBlock();
queryString = queryString.arg(tableName());
queryString = queryString.arg(table());
if (!q.prepare(queryString)) {
return PrepareResult::Fail;
@ -53,17 +44,6 @@ PrepareResult DBObject::prepareSelectQuery(QSqlQuery &q) const {
return PrepareResult::Success;
}
bool DBObject::fromSqlRecord(const QSqlRecord &q) {
QString key = primaryKey();
if (key.size() && q.contains(key)) {
setId(q.value(key));
return true;
}
return false;
}
PrepareResult DBObject::prepareInsertQuery(QSqlQuery &q) const {
DBVariantMap map = variantMap();
@ -78,7 +58,7 @@ PrepareResult DBObject::prepareInsertQuery(QSqlQuery &q) const {
QString queryString = "INSERT INTO %0(%1) VALUES (%2) ";
queryString = queryString.arg(tableName());
queryString = queryString.arg(table());
QString tableInsertHeader = "";
QString tableInsertValues = "";
@ -129,7 +109,7 @@ PrepareResult DBObject::prepareUpdateQuery(QSqlQuery &q) const {
QString queryString = "UPDATE %0 SET %1 WHERE " + condition();
queryString = queryString.arg(tableName());
queryString = queryString.arg(table());
QString tableUpdateValues = "";
for (auto it = map.begin(); it != map.end(); ++it) {
@ -183,7 +163,7 @@ bool DBObject::isBundle() const {
}
uint DBObject::dbKey() const {
return HASH_KEY(DbAddressKey(_dbId));
return HASH_KEY(DbAddressKey(dbAddress()));
}
QString DBObject::condition() const {
@ -204,21 +184,9 @@ QString DBObject::condition() const {
QString errorString = "WRONG OBJECT";
// if object have a primaryKey then return primary key
auto primaryVal = getId();
if (primaryVal.isValid()) {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
bool fWarning = primaryVal.type() == QVariant::ByteArray;
#else
bool fWarning = primaryVal.metaType().id() == QMetaType::QByteArray;
#endif
if (fWarning) {
byteArrayWarning();
return errorString;
}
return prepareCondition(primaryKey(), primaryVal.toString());
auto primaryVal = primaryValue();
if (primaryVal.size()) {
return prepareCondition(primaryKey(), primaryVal);
}
auto map = variantMap();
@ -266,20 +234,12 @@ QString DBObject::condition() const {
return errorString;
}
const QVariant &DBObject::primaryValue() const {
return _dbId.id();
}
void DBObject::setDbAddress(const DbAddress &address) {
_dbId = address;
}
bool DBObject::isInsertPrimaryKey() const {
return bool(variantMap().value(primaryKey()).type & MemberType::Insert);
}
const DbAddress &DBObject::dbAddress() const {
return _dbId;
DbAddress DBObject::dbAddress() const {
return {table(), primaryValue()};
}
DBObject *DBObject::cloneRaw() const {
@ -293,7 +253,7 @@ DBObject *DBObject::cloneRaw() const {
QString DBObject::toString() const {
return AbstractData::toString() +
QString(" %0").arg(_dbId.toString());
QString(" %0").arg(dbAddress().toString());
}
QString DBObject::getWhereBlock() const {
@ -315,11 +275,27 @@ void DBObject::setPrintError(bool newPrintError) {
_printError = newPrintError;
}
QDataStream &DBObject::fromStream(QDataStream &stream) {
QuasarAppUtils::Params::log("This object not support stream operator."
" Please Override the fromStream method for this object. " + toString(),
QuasarAppUtils::Warning);
return stream;
}
QDataStream &DBObject::toStream(QDataStream &stream) const {
QuasarAppUtils::Params::log("This object not support stream operator."
" Please Override the toStream method for this object. " + toString(),
QuasarAppUtils::Warning);
return stream;
}
PrepareResult DBObject::prepareRemoveQuery(QSqlQuery &q) const {
QString queryString = "DELETE FROM %0 " + getWhereBlock();
queryString = queryString.arg(tableName());
queryString = queryString.arg(table());
if (!q.prepare(queryString)) {
return PrepareResult::Fail;
@ -328,25 +304,9 @@ PrepareResult DBObject::prepareRemoveQuery(QSqlQuery &q) const {
return PrepareResult::Success;
}
QDataStream &DBObject::fromStream(QDataStream &stream) {
AbstractData::fromStream(stream);
stream >> _dbId;
return stream;
}
QDataStream &DBObject::toStream(QDataStream &stream) const {
AbstractData::toStream(stream);
stream << _dbId;
return stream;
}
DBVariantMap DBObject::variantMap() const {
if (isHaveAPrimaryKey()) {
return {{primaryKey(), {_dbId.id(), MemberType::PrimaryKey}}};
return {{primaryKey(), {primaryValue(), MemberType::PrimaryKey}}};
}
return {};
@ -357,23 +317,14 @@ bool DBObject::isValid() const {
return false;
if (isInsertPrimaryKey()) {
return _dbId.isValid();
return primaryValue().size();
}
return _dbId.table().size();
return table().size();
}
bool DBObject::copyFrom(const AbstractData * other) {
if (!AbstractData::copyFrom(other))
return false;
auto otherObject = dynamic_cast<const DBObject*>(other);
if (!otherObject)
return false;
this->_dbId = otherObject->_dbId;
return true;
return AbstractData::copyFrom(other);
}
unsigned int DBObject::subscribeId() const {
@ -388,17 +339,7 @@ bool DBObject::isHaveAPrimaryKey() const {
return primaryKey().size();
}
const QVariant& DBObject::getId() const {
return dbAddress().id();
}
void DBObject::setId(const QVariant& id) {
_dbId.setId(id);
}
void DBObject::clear() {
setId({});
}
void DBObject::clear() {}
DBVariant::DBVariant() {

@ -102,12 +102,7 @@ class HEARTSHARED_EXPORT DBObject : public AbstractData, public ISubscribableDat
public:
/**
* @brief DBObject This is default constructor.Before using this class you need set the table name and primary key of this object.
* @param tableName This is table name.
*/
DBObject(const QString& tableName);
DBObject(const DbAddress& address);
DBObject();
~DBObject() override;
@ -129,30 +124,13 @@ public:
*/
bool isHaveAPrimaryKey() const;
/**
* @brief getId This method return id of database object. The database id it is pair of an id member of table and a table name.
* @return The id of database object.
*/
const QVariant &getId() const;
/**
* @brief setId This method set new id for current database object.
* @param id This is new value of id.
*/
void setId(const QVariant& id);
/**
* @brief clear This method clear all data of database object.
* Override This method for remove or reset your own members of class.
* @note The Default implementation do nothing
*/
virtual void clear();
/**
* @brief tableName This method return a table name of the database object.
* @return string value if the table name.
*/
QString tableName() const;
/**
* @brief createDBObject This method should be create a object with the some type as the object called this method.
* Example of override:
@ -190,16 +168,14 @@ public:
* Exampel of override fromSqlRecord method:
* \code{cpp}
* bool ExampleObject::fromSqlRecord(const QSqlRecord &q) {
if (!DBObject::fromSqlRecord(q)) {
return false;
}
id = q.value("id").toInt();
exampleMember = q.value("exampleMember").toInt();
return isValid();
}
* \endcode
*/
virtual bool fromSqlRecord(const QSqlRecord& q);
virtual bool fromSqlRecord(const QSqlRecord& q) = 0;
/**
* @brief prepareInsertQuery This method should be prepare a query for insert object into database.
@ -227,7 +203,7 @@ public:
QString queryString = "INSERT INTO %0(%1) VALUES (%2) ";
queryString = queryString.arg(tableName());
queryString = queryString.arg(table());
QString tableInsertHeader = "";
QString tableInsertValues = "";
@ -281,7 +257,7 @@ public:
QString queryString = "UPDATE %0 SET %1 WHERE %2";
queryString = queryString.arg(tableName());
queryString = queryString.arg(table());
QString tableUpdateValues = "";
QString tableUpdateRules = QString("%0 = :%0").
arg(primaryKey());
@ -368,7 +344,7 @@ public:
* IF the object is not valid then this method return an invalid database address.
* @return The database address of current object.
*/
const DbAddress& dbAddress() const;
DbAddress dbAddress() const;
/**
* @brief clone This method create a new object. The new Object is clone of current object.
@ -426,6 +402,12 @@ public:
*/
virtual DBVariantMap variantMap() const;
/**
* @brief table This method should be return name of the database table that should be contains objects with this type.
* @return table name that contains object with this type.
*/
virtual QString table() const = 0;
/**
* @brief printError This method return status of printing error messages for sql quries. by default this propertye is enabled.
* @return true if printing error messages is enabled else false.
@ -474,15 +456,10 @@ protected:
/**
* @brief primaryValue This method is wraper of DBAddress::id. If This object do not contains a id value then return invalid value.
* @return Value of primaryKey ( database id ).
* @note If you alredy override the condition method then You can return empty string because this method using in generate default condition only.
* @see DBObject::condition.
*/
const QVariant& primaryValue() const;
/**
* @brief setDbAddress This method set the new database address.
* @param address This is a new value of database address.
*/
void setDbAddress(const DbAddress &address);
virtual QString primaryValue() const = 0;
/**
* @brief isInsertPrimaryKey This method check primaryKeys type.
@ -494,8 +471,6 @@ protected:
private:
QString getWhereBlock() const;
bool _printError = true;
DbAddress _dbId;
};
}
}

@ -8,9 +8,8 @@
#include "dbobjectset.h"
namespace QH {
namespace PKG {
DBObjectSet::DBObjectSet(const QString table):
DBObject(table) {
DBObjectSet::DBObjectSet(const QString table) {
_table = table;
}
PrepareResult DBObjectSet::prepareInsertQuery(QSqlQuery &) const {
@ -41,6 +40,10 @@ QString DBObjectSet::primaryKey() const {
return "";
}
QString DBObjectSet::table() const {
return _table;
}
}
}

@ -27,8 +27,6 @@ class HEARTSHARED_EXPORT DBObjectSet: public DBObject
public:
DBObjectSet(const QString table);
// DBObject interface
public:
PrepareResult prepareInsertQuery(QSqlQuery &) const override final;
PrepareResult prepareRemoveQuery(QSqlQuery &q) const override final;
PrepareResult prepareSelectQuery(QSqlQuery &q) const override final;
@ -37,6 +35,10 @@ public:
bool isCached() const override final;
bool isBundle() const override final;
QString primaryKey() const override;
QString table() const override;
private:
QString _table;
};
}

@ -56,6 +56,14 @@ public:
_conditions = conditions;
};
QString primaryValue() const override {
return "";
}
QString primaryKey() const override {
return "";
}
void clear() override {
_data.clear();
};
@ -73,6 +81,14 @@ public:
return true;
};
QDataStream &fromStream(QDataStream &stream) override {
return stream;
};
QDataStream &toStream(QDataStream &stream) const override {
return stream;
};
bool isValid() const override {
return true;
};
@ -108,7 +124,7 @@ protected:
}
DBObject *createDBObject() const override {
return create<DBObjectsRequest<T>>(tableName(), _conditions);
return create<DBObjectsRequest<T>>(table(), _conditions);
};
QList<QSharedPointer<T>> _data;

@ -49,7 +49,6 @@ protected:
QDataStream &fromStream(QDataStream &stream) override {
DBObjectSet::fromStream(stream);
clear();
int size = 0;
stream >> size;

@ -10,7 +10,7 @@ namespace QH {
namespace PKG {
DefaultPermision::DefaultPermision():
MemberPermisionObject("DefaultPermissions") {
MemberPermisionObject() {
}
@ -48,5 +48,9 @@ QString DefaultPermision::condition() const {
return result;
}
QString DefaultPermision::table() const {
return "DefaultPermissions";
}
}
}

@ -34,6 +34,8 @@ public:
bool fromSqlRecord(const QSqlRecord &q) override;
DBObject *createDBObject() const override;
QString condition() const override;
QString table () const override;
};
}
}

@ -8,7 +8,7 @@
#include "deleteobject.h"
namespace QH {
namespace PKG {
DeleteObject::DeleteObject(): DBObject("") {
DeleteObject::DeleteObject() {
}
@ -32,21 +32,21 @@ void DeleteObject::setSignToken(const AccessToken &token) {
_token = token;
}
QString DeleteObject::primaryKey() const {
return "id";
bool DeleteObject::fromSqlRecord(const QSqlRecord &q) {
Q_UNUSED(q);
return true;
}
QDataStream &DeleteObject::fromStream(QDataStream &stream) {
DBObject::fromStream(stream);
stream >> _address;
stream >> _token;
return stream;
}
QDataStream &DeleteObject::toStream(QDataStream &stream) const {
DBObject::toStream(stream);
stream << _address;
stream << _token;
return stream;
@ -55,5 +55,26 @@ QDataStream &DeleteObject::toStream(QDataStream &stream) const {
bool DeleteObject::isCached() const {
return false;
}
QString DeleteObject::table() const {
return _address.table();
}
const DbAddress &DeleteObject::address() const {
return _address;
}
void DeleteObject::setAddress(const DbAddress &newAddress) {
_address = newAddress;
}
QString DeleteObject::primaryKey() const {
return "id";
}
QString DeleteObject::primaryValue() const {
return _address.id().toString();
}
}
}

@ -30,16 +30,34 @@ public:
const AccessToken &getSignToken() const override;
void setSignToken(const AccessToken &token) override;
bool fromSqlRecord(const QSqlRecord &q) override;
bool isCached() const override;
QString table() const override;
/**
* @brief address This method return address of the object that will be deleted.
* @return database address of the object that will be deleted.
*/
const DbAddress &address() const;
/**
* @brief setAddress This method sets new address for object that will be deleted from database.
* @param newAddress This is new value of the database adderess.
*/
void setAddress(const DbAddress &newAddress);
protected:
QString primaryKey() const override;
QString primaryValue() const override;
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
// DBObject interface
public:
bool isCached() const override;
private:
DbAddress _address;
AccessToken _token;
};

@ -8,9 +8,9 @@ namespace QH {
namespace PKG {
GetMaxIntegerId::GetMaxIntegerId(const QString& table, const QString& field):
DBObject(table) {
GetMaxIntegerId::GetMaxIntegerId(const QString& table, const QString& field) {
_table = table;
_field = field;
}
@ -19,13 +19,13 @@ int GetMaxIntegerId::value() const {
}
DBObject *GetMaxIntegerId::createDBObject() const {
return create<GetMaxIntegerId>(tableName(), _field);
return create<GetMaxIntegerId>(table(), _field);
}
PrepareResult GetMaxIntegerId::prepareSelectQuery(QSqlQuery &q) const {
QString queryString = "SELECT max(%0) FROM %1";
queryString = queryString.arg(_field, tableName());
queryString = queryString.arg(_field, table());
if (!q.prepare(queryString)) {
return PrepareResult::Fail;
@ -44,9 +44,17 @@ bool GetMaxIntegerId::isCached() const {
return false;
}
QString GetMaxIntegerId::table() const {
return _table;
}
QString GetMaxIntegerId::primaryKey() const {
return "";
}
QString GetMaxIntegerId::primaryValue() const {
return "";
}
}
}

@ -39,12 +39,14 @@ public:
PrepareResult prepareSelectQuery(QSqlQuery &q) const override;
bool fromSqlRecord(const QSqlRecord &q) override;
bool isCached() const override;
QString table() const override;
protected:
QString primaryKey() const override;
QString primaryValue() const override;
private:
QString _table;
QString _field;
int _value;
};

@ -14,9 +14,12 @@ namespace QH {
namespace PKG {
GetSingleValue::GetSingleValue(const DbAddress& address, const QString& field, const QString& primaryKey):
DBObject(address) {
GetSingleValue::GetSingleValue(const DbAddress& address,
const QString& field,
const QString& primaryKey) {
_table = address.table();
_id = address.id().toString();
_field = field;
_key = primaryKey;
}
@ -32,7 +35,7 @@ DBObject *GetSingleValue::createDBObject() const {
PrepareResult GetSingleValue::prepareSelectQuery(QSqlQuery &q) const {
QString queryString = "SELECT %0 FROM %1 WHERE %2='%3'";
queryString = queryString.arg(_field, tableName(), _key, getId().toString());
queryString = queryString.arg(_field, table(), _key, _id);
if (!q.prepare(queryString)) {
return PrepareResult::Fail;
@ -51,8 +54,16 @@ bool GetSingleValue::isCached() const {
return false;
}
QString GetSingleValue::table() const {
return _table;
}
QString GetSingleValue::primaryKey() const {
return _key;
return _id;
}
QString GetSingleValue::primaryValue() const {
return _field;
}
}

@ -59,13 +59,15 @@ public:
PrepareResult prepareSelectQuery(QSqlQuery &q) const override;
bool fromSqlRecord(const QSqlRecord &q) override;
bool isCached() const override;
QString table() const override;
protected:
QString primaryKey() const override;
QString primaryValue() const override;
private:
QString _id;
QString _field;
QString _table;
QVariant _value;
QString _key;

@ -14,8 +14,7 @@
namespace QH {
namespace PKG {
MemberPermisionObject::MemberPermisionObject():
MemberPermisionObject("MemberPermisions") {
MemberPermisionObject::MemberPermisionObject() {
}
@ -30,11 +29,6 @@ MemberPermisionObject::MemberPermisionObject(const PermisionData &id):
setKey(id);
}
MemberPermisionObject::MemberPermisionObject(const QString &tableName):
DBObject(tableName) {
}
bool MemberPermisionObject::isValid() const {
return _key.isValid();
}
@ -92,9 +86,13 @@ QDataStream &MemberPermisionObject::toStream(QDataStream &stream) const {
}
DBVariantMap MemberPermisionObject::variantMap() const {
return {{"memberId", {_key.id(), MemberType::InsertUpdate}},
{"dbAddress", {_key.addressHash(), MemberType::InsertUpdate}},
{"lvl", {static_cast<unsigned char>(_permision), MemberType::InsertUpdate}}};
return {{"memberId", {_key.id(), MemberType::InsertUpdate}},
{"dbAddress", {_key.addressHash(), MemberType::InsertUpdate}},
{"lvl", {static_cast<unsigned char>(_permision), MemberType::InsertUpdate}}};
}
QString MemberPermisionObject::table() const {
return "MemberPermisions";
}
QString MemberPermisionObject::condition() const {
@ -117,13 +115,16 @@ QString MemberPermisionObject::primaryKey() const {
return "";
}
QString MemberPermisionObject::primaryValue() const {
return "";
}
PermisionData MemberPermisionObject::key() const {
return _key;
}
void MemberPermisionObject::setKey(const PermisionData &key) {
_key = key;
setId(_key.hash());
}
Permission MemberPermisionObject::permisions() const {

@ -40,6 +40,8 @@ public:
bool isCached() const override;
DBVariantMap variantMap() const override;
QString table() const override;
/**
* @brief permisions This method return value permission of object.
* For select object set it id using a MemberPermisionObject::setKey method.
@ -66,17 +68,13 @@ public:
void setKey(const PermisionData &key);
protected:
/**
* @brief MemberPermisionObject This is protected constructor for support inheritance functions.
*/
MemberPermisionObject(const QString& tableName);
// StreamBase interface
QDataStream &fromStream(QDataStream &stream) override;
QDataStream &toStream(QDataStream &stream) const override;
QString condition() const override;
QString primaryKey() const override;
QString primaryValue() const override;
private:
Permission _permision;

@ -14,7 +14,7 @@ NetworkMember::NetworkMember() {
}
NetworkMember::NetworkMember(const QVariant &id): AbstractNetworkMember(id) {
NetworkMember::NetworkMember(const QString &id): AbstractNetworkMember(id) {
}

@ -24,7 +24,7 @@ class HEARTSHARED_EXPORT NetworkMember: public AbstractNetworkMember
public:
NetworkMember();
NetworkMember(const QVariant& id);
NetworkMember(const QString& id);
public:
DBObject *createDBObject() const override;

@ -19,9 +19,9 @@ namespace PKG {
SetSingleValue::SetSingleValue(const DbAddress& address,
const QString& field,
const QVariant& value,
const QString &primaryKey):
DBObject(address)
{
const QString &primaryKey) {
_id = address.id().toString();
_table = address.table();
_field = field;
_value = value;
_primaryKey = primaryKey;
@ -34,7 +34,7 @@ DBObject *SetSingleValue::createDBObject() const {
PrepareResult SetSingleValue::prepareUpdateQuery(QSqlQuery &q) const {
QString queryString = "UPDATE %0 SET %1=:%1 WHERE %2='%3'";
queryString = queryString.arg(tableName(), _field, primaryKey(), getId().toString());
queryString = queryString.arg(table(), _field, primaryKey(), _id);
if (!q.prepare(queryString)) {
@ -51,7 +51,7 @@ PrepareResult SetSingleValue::prepareUpdateQuery(QSqlQuery &q) const {
PrepareResult SetSingleValue::prepareInsertQuery(QSqlQuery &q) const {
QString queryString = "INSERT INTO %0 (%1, %2) VALUES (:%1, :%2)";
queryString = queryString.arg(tableName(), primaryKey(), _field);
queryString = queryString.arg(table(), primaryKey(), _field);
if (!q.prepare(queryString)) {
@ -60,7 +60,7 @@ PrepareResult SetSingleValue::prepareInsertQuery(QSqlQuery &q) const {
return PrepareResult::Fail;
}
q.bindValue(":" + primaryKey(), getId().toString());
q.bindValue(":" + primaryKey(), primaryValue());
q.bindValue(":" + _field, _value);
return PrepareResult::Success;
@ -74,8 +74,16 @@ bool SetSingleValue::isCached() const {
return false;
}
QString SetSingleValue::table() const {
return _table;
}
QString SetSingleValue::primaryKey() const {
return _primaryKey;
}
QString SetSingleValue::primaryValue() const {
return _id;
}
}
}

@ -54,11 +54,16 @@ public:
bool fromSqlRecord(const QSqlRecord &q) override;
bool isCached() const override;
QString table() const override;
protected:
QString primaryKey() const override;
QString primaryValue() const override;
private:
QString _id;
QString _table;
QString _field;
QString _primaryKey;
QVariant _value;

@ -13,7 +13,7 @@ UserMember::UserMember(const Package &pkg):
fromBytes(pkg.data);
}
UserMember::UserMember(const QVariant &id):
UserMember::UserMember(const QString &id):
UserMember() {
setId(id);
}

@ -26,7 +26,7 @@ class HEARTSHARED_EXPORT UserMember: public AbstractNetworkMember
public:
UserMember();
UserMember(const Package &pkg);
UserMember(const QVariant &id);
UserMember(const QString &id);
bool copyFrom(const AbstractData *other) override;
bool fromSqlRecord(const QSqlRecord &q) override;

@ -23,7 +23,6 @@ WebSocket::WebSocket(const Package &package):
}
QDataStream &WebSocket::fromStream(QDataStream &stream) {
AbstractData::fromStream(stream);
stream >> _request;
stream >> _subscribeId;
@ -31,7 +30,6 @@ QDataStream &WebSocket::fromStream(QDataStream &stream) {
}
QDataStream &WebSocket::toStream(QDataStream &stream) const {
AbstractData::toStream(stream);
stream << _request;
stream << _subscribeId;

@ -26,13 +26,11 @@ WebSocketSubscriptions::WebSocketSubscriptions(const QH::Package &package):
}
QDataStream &WebSocketSubscriptions::fromStream(QDataStream &stream) {
AbstractData::fromStream(stream);
return stream >> _subscribeIds;
}
QDataStream &WebSocketSubscriptions::toStream(QDataStream &stream) const {
AbstractData::toStream(stream);
return stream << _subscribeIds;
}

@ -155,7 +155,8 @@ bool SingleClient::removeUser() {
QH::PKG::DeleteObject request;
request.copyFrom(&getMember());
request.setAddress(getMember().dbAddress());
if (!sendData(&request, realServerAddress())) {
return false;
};

@ -51,8 +51,8 @@ bool SqlDBWriter::exec(QSqlQuery *sq, const QString& sqlFile) const {
temp = temp.remove(0, delimiterIndex + 1);
if (!result) {
QuasarAppUtils::Params::log(QString("exec database error. line:%0: %1").
arg(lineNumber).arg(sq->lastError().text()),
QuasarAppUtils::Params::log(QString("Exec database error. File: %0. Line:%1: %2").
arg(sqlFile).arg(lineNumber).arg(sq->lastError().text()),
QuasarAppUtils::Error);
f.close();
return false;
@ -137,10 +137,10 @@ bool SqlDBWriter::doQueryPrivate(const QString &query, QSqlQuery* result) const
return false;
}
QSqlQuery q(query, *db());
if (!q.exec()) {
QuasarAppUtils::Params::log("request error : " + q.lastError().text());
QSqlQuery q(*db());
if (!q.exec(query)) {
QuasarAppUtils::Params::log("request error : " + q.lastError().text(),
QuasarAppUtils::Error);
return false;
}
@ -391,7 +391,9 @@ bool SqlDBWriter::selectQuery(const DBObject& requestObject,
while (q.next()) {
if (!newObject->fromSqlRecord(q.record())) {
QuasarAppUtils::Params::log("Init sql object error.",
QuasarAppUtils::Params::log("Select query finished successful but, "
"the fromSqlRecord method return false." +
newObject->toString(),
QuasarAppUtils::Error);
return false;
}
@ -466,11 +468,12 @@ bool SqlDBWriter::workWithQuery(QSqlQuery &q,
if (!printErrors)
return ;
QuasarAppUtils::Params::log("prepare sql error: " + q.executedQuery(),
QuasarAppUtils::Debug);
QuasarAppUtils::Params::log("exec sql error: " + q.lastError().text(),
QuasarAppUtils::Error);
QuasarAppUtils::Params::log("prepare sql error: " + q.executedQuery(),
QuasarAppUtils::Error);
};

@ -21,7 +21,7 @@ WebSocketController::WebSocketController(DataBaseNode *node) {
}
void WebSocketController::subscribe(const QVariant &subscriber,
void WebSocketController::subscribe(const QString &subscriber,
unsigned int item) {
_subscribsMutex.lock();
@ -33,7 +33,7 @@ void WebSocketController::subscribe(const QVariant &subscriber,
_subscribsMutex.unlock();
}
void WebSocketController::unsubscribe(const QVariant &subscriber,
void WebSocketController::unsubscribe(const QString &subscriber,
unsigned int item) {
_subscribsMutex.lock();
_itemsMutex.lock();
@ -44,7 +44,7 @@ void WebSocketController::unsubscribe(const QVariant &subscriber,
_subscribsMutex.unlock();
}
QSet<unsigned int> WebSocketController::list(const QVariant &subscriber) {
QSet<unsigned int> WebSocketController::list(const QString &subscriber) {
QMutexLocker locker(&_itemsMutex);
return _items[subscriber];
}
@ -56,14 +56,14 @@ void WebSocketController::handleItemChanged(const QSharedPointer<ISubscribableDa
}
void WebSocketController::foreachSubscribers(const QSharedPointer<ISubscribableData> &item,
const QSet<QVariant> &subscribersList) {
const QSet<QString> &subscribersList) {
for (const auto &subscriber : subscribersList) {
auto abstractItem = item.dynamicCast<AbstractData>();
if (!abstractItem) {
QuasarAppUtils::Params::log("All Subsribable objects must be child classes of the AbstractData." + subscriber.toString(),
QuasarAppUtils::Params::log("All Subsribable objects must be child classes of the AbstractData." + subscriber,
QuasarAppUtils::Error);
unsubscribePrivate(subscriber, item->subscribeId());
@ -78,7 +78,7 @@ void WebSocketController::foreachSubscribers(const QSharedPointer<ISubscribableD
}
if (fAllowed && !_node->sendData(abstractItem.data(), subscriber)) {
QuasarAppUtils::Params::log("Send update failed for " + subscriber.toString(),
QuasarAppUtils::Params::log("Send update failed for " + subscriber,
QuasarAppUtils::Warning);
unsubscribePrivate(subscriber, item->subscribeId());
@ -86,20 +86,20 @@ void WebSocketController::foreachSubscribers(const QSharedPointer<ISubscribableD
if (!fAllowed) {
QuasarAppUtils::Params::log(QString("Internal Error. Member:%0 not have permission to object %1").
arg(subscriber.toString(), abstractItem->toString()),
arg(subscriber, abstractItem->toString()),
QuasarAppUtils::Error);
unsubscribePrivate(subscriber, item->subscribeId());
}
}
}
void WebSocketController::unsubscribePrivate(const QVariant &subscriber,
void WebSocketController::unsubscribePrivate(const QString &subscriber,
unsigned int item) {
_subscribs[item].remove(subscriber);
_items[subscriber].remove(item);
}
void WebSocketController::subscribePrivate(const QVariant &subscriber,
void WebSocketController::subscribePrivate(const QString &subscriber,
unsigned int item) {
_subscribs[item].insert(subscriber);

@ -38,7 +38,7 @@ public:
* @param item This is a subscribable object id.
* @return true if method finished successful.
*/
void subscribe(const QVariant &subscriber,
void subscribe(const QString &subscriber,
unsigned int item);
/**
@ -47,7 +47,7 @@ public:
* @param item This is a subscribable object id.
* @return true if method finished successful.
*/
void unsubscribe(const QVariant &subscriber,
void unsubscribe(const QString &subscriber,
unsigned int item);
/**
@ -55,7 +55,7 @@ public:
* @param subscriber This is network member that want get a list of own subscription.
* @return true if method finished successful.
*/
QSet<unsigned int> list(const QVariant& subscriber);
QSet<unsigned int> list(const QString& subscriber);
/**
* @brief handleItemChanged This method invoked when item on database changed.
@ -65,17 +65,17 @@ public:
private:
void foreachSubscribers(const QSharedPointer<PKG::ISubscribableData> &item,
const QSet<QVariant> &subscribersList);
const QSet<QString> &subscribersList);
void unsubscribePrivate(const QVariant &subscriber,
void unsubscribePrivate(const QString &subscriber,
unsigned int item);
void subscribePrivate(const QVariant &subscriber,
void subscribePrivate(const QString &subscriber,
unsigned int item);
/// subscribers it is nodes or clients
QHash<unsigned int, QSet<QVariant>> _subscribs;
QHash<QVariant, QSet<unsigned int>> _items;
QHash<unsigned int, QSet<QString>> _subscribs;
QHash<QString, QSet<unsigned int>> _items;
QMutex _subscribsMutex;
QMutex _itemsMutex;

@ -47,12 +47,10 @@ public:
protected:
// StreamBase interface override this methods for serialization your package
QDataStream &fromStream(QDataStream &stream) {
AbstractData::fromStream(stream);
stream >> _data;
return stream;
}
QDataStream &toStream(QDataStream &stream) const {
AbstractData::toStream(stream);
stream << _data;
return stream;
}

@ -10,7 +10,6 @@
#include "testutils.h"
#include <abstractnode.h>
#include <keystorage.h>
#include <ping.h>
#define LOCAL_TEST_PORT TEST_PORT + 1

@ -22,16 +22,12 @@ public:
// StreamBase interface
protected:
QDataStream &fromStream(QDataStream &stream) override{
AbstractData::fromStream(stream);
stream >> data;
return stream;
};
QDataStream &toStream(QDataStream &stream) const override{
AbstractData::toStream(stream);
stream << data;
return stream;

@ -6,9 +6,9 @@
*/
#include "ecdsaauthtest.h"
#include "authecdsa.h"
#include <QtTest>
#include "thread"
#include <hcryptoFeatures/authecdsa.h>
#include <thread>
#ifdef USE_HEART_SSL

@ -12,7 +12,6 @@
#include <databasenode.h>
#include <hostaddress.h>
#include <keystorage.h>
#include <ping.h>
#define LOCAL_TEST_PORT TEST_PORT + 2

@ -96,7 +96,7 @@ protected:
// create request for get all objects from database.
QH::PKG::DBObjectsRequest<WorkType> setRequest(
testObjec->tableName(), "");
testObjec->table(), "");
auto list = BASE::db()->getObject(setRequest);
QVERIFY(list);
@ -181,7 +181,7 @@ protected:
QVERIFY(BASE::run( _dbNodeName));
QVERIFY(!BASE::changeTrust(QVariant{}, -10));
QVERIFY(!BASE::changeTrust("", -10));
QVERIFY(BASE::changeTrust(testObjec->getId(), -10));

@ -7,6 +7,8 @@
#include <QtTest>
#include <isqldbcache.h>
#include <database.h>
#include <qaglobalutils.h>
#define LOCAL_TEST_PORT TEST_PORT + 5
class UpgradableDatabase: public QH::DataBase {
@ -15,6 +17,10 @@ class UpgradableDatabase: public QH::DataBase {
// DataBaseNode interface
public:
UpgradableDatabase() {
initDBPatches();
}
bool checkVersion(int version) {
QSqlQuery query;
if (!db()->doQuery("SELECT * FROM DataBaseAttributes WHERE name='version'", true, &query)){
@ -31,38 +37,47 @@ public:
protected:
void initDBPatches() {
QH::DBPatchMap dbPatches() const {
QH::DBPatchMap result;
addDBPatch({
0, // from version
1, // to version
result += [](const QH::iObjectProvider* database) -> bool {
QSqlQuery query;
if (!database->doQuery("select * from DataBaseAttributes", true, &query)){
return false;
};
[](const QH::iObjectProvider* database) -> bool {
QSqlQuery query;
if (!database->doQuery("select * from DataBaseAttributes", true, &query)){
return false;
};
return true;
};
return true;
} // action of patch
});
result += [](const QH::iObjectProvider* database) -> bool {
QSqlQuery query;
if (!database->doQuery("select * from DataBaseAttributes", true, &query)){
return false;
};
addDBPatch({
1, // from version
2, // to version
[](const QH::iObjectProvider* database) -> bool {
QSqlQuery query;
if (!database->doQuery("select * from DataBaseAttributes", true, &query)){
return false;
};
return true;
};
return true;
}
});
result += [](const QH::iObjectProvider* database) -> bool {
QSqlQuery query;
if (!database->doQuery("select * from DataBaseAttributes", true, &query)){
return false;
};
addDBPatch({
2, // from version
3, // to version
[](const QH::iObjectProvider* database) -> bool {
QSqlQuery query;
if (!database->doQuery("select * from DataBaseAttributes", true, &query)){
return false;
};
return true;
};
return result;
return true;
}
});
}
};

@ -1 +1 @@
Subproject commit 4c596e30882931312b2beb31f8020351e719b2ce
Subproject commit c492fa2fe8b83f93806cc31498af66ee053630ae