Skip to content

Commit 8a0a059

Browse files
committed
#RI-4146 - add PHP GZCompress decompression
1 parent c062504 commit 8a0a059

File tree

10 files changed

+78
-7
lines changed

10 files changed

+78
-7
lines changed

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@
128128
"@types/jsonpath": "^0.2.0",
129129
"@types/lodash": "^4.14.171",
130130
"@types/node": "14.14.10",
131+
"@types/pako": "^2.0.0",
131132
"@types/react": "^18.0.20",
132133
"@types/react-dom": "^18.0.5",
133134
"@types/react-redux": "^7.1.12",
@@ -233,6 +234,7 @@
233234
"electron-log": "^4.2.4",
234235
"electron-store": "^8.0.0",
235236
"electron-updater": "^5.0.5",
237+
"fflate": "^0.7.4",
236238
"file-saver": "^2.0.5",
237239
"formik": "^2.2.9",
238240
"fzstd": "^0.1.0",
@@ -244,6 +246,7 @@
244246
"jsonpath": "^1.1.1",
245247
"lodash": "^4.17.21",
246248
"lz4js": "^0.2.0",
249+
"pako": "^2.1.0",
247250
"php-serialize": "^4.0.2",
248251
"rawproto": "^0.7.6",
249252
"react": "^18.2.0",

redisinsight/api/src/modules/database/entities/database.entity.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export enum Compressor {
3232
LZ4 = 'LZ4',
3333
SNAPPY = 'SNAPPY',
3434
Brotli = 'Brotli',
35+
PHPGZCompress = 'PHPGZCompress',
3536
}
3637

3738
@Entity('database_instance')

redisinsight/ui/src/constants/keys.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ export enum KeyValueCompressor {
187187
LZ4 = 'LZ4',
188188
SNAPPY = 'SNAPPY',
189189
Brotli = 'Brotli',
190-
// PHPGZCompress = 'PHPGZCompress',
190+
PHPGZCompress = 'PHPGZCompress',
191191
}
192192

193193
export const COMPRESSOR_MAGIC_SYMBOLS: ICompressorMagicSymbols = Object.freeze({
@@ -196,6 +196,7 @@ export const COMPRESSOR_MAGIC_SYMBOLS: ICompressorMagicSymbols = Object.freeze({
196196
[KeyValueCompressor.LZ4]: '4,34,77,24', // 04 22 4d 18 hex
197197
[KeyValueCompressor.SNAPPY]: '', // no magic symbols
198198
[KeyValueCompressor.Brotli]: '', // no magic symbols
199+
[KeyValueCompressor.PHPGZCompress]: '', // no magic symbols
199200
})
200201

201202
export type ICompressorMagicSymbols = {

redisinsight/ui/src/pages/home/components/AddInstanceForm/InstanceForm/form-components/DbCompressor.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ const DbCompressor = (props: Props) => {
4949
{
5050
value: KeyValueCompressor.Brotli,
5151
inputDisplay: 'Brotli'
52-
}
52+
},
53+
{
54+
value: KeyValueCompressor.PHPGZCompress,
55+
inputDisplay: 'PHP GZCompress'
56+
},
5357
]
5458

5559
const handleChangeDbCompressorCheckbox = (e: ChangeEvent<HTMLInputElement>): void => {

redisinsight/ui/src/utils/decompressors/decompressors.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import { forIn } from 'lodash'
22
import { unzip } from 'gzip-js'
33
import { decompress as decompressFzstd } from 'fzstd'
4+
// @ts-ignore
45
import { decompress as decompressLz4 } from 'lz4js'
56
import { decompress as decompressSnappy } from '@stablelib/snappy'
7+
// @ts-ignore
68
import { decompress as decompressBrotli } from 'brotli-unicode/js'
9+
import { inflate } from 'pako'
710
import { COMPRESSOR_MAGIC_SYMBOLS, ICompressorMagicSymbols, KeyValueCompressor } from 'uiSrc/constants'
811
import { RedisResponseBuffer, RedisString } from 'uiSrc/slices/interfaces'
9-
import { anyToBuffer, bufferToString, isEqualBuffers, Nullable } from 'uiSrc/utils'
12+
import { anyToBuffer, bufferToString, bufferToUint8Array, isEqualBuffers, Nullable } from 'uiSrc/utils'
1013

1114
const decompressingBuffer = (
1215
reply: RedisResponseBuffer,
@@ -66,6 +69,17 @@ const decompressingBuffer = (
6669
isCompressed: !isEqualBuffers(value, reply),
6770
}
6871
}
72+
case KeyValueCompressor.PHPGZCompress: {
73+
const decompressedValue = inflate(bufferToUint8Array(reply))
74+
if (!decompressedValue) return { value: reply, compressor: null, isCompressed: false }
75+
76+
const value = anyToBuffer(decompressedValue)
77+
return {
78+
value,
79+
compressor,
80+
isCompressed: !isEqualBuffers(value, reply),
81+
}
82+
}
6983
default: {
7084
return { value: reply, compressor: null, isCompressed: false }
7185
}

redisinsight/ui/src/utils/formatters/bufferFormatters.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ const ASCIIToBuffer = (strInit: string) => {
106106
return anyToBuffer(Array.from(Buffer.from(result, 'hex')))
107107
}
108108

109-
const bufferToUTF8 = (reply: RedisResponseBuffer): string => decoder.decode(new Uint8Array(reply.data))
109+
const bufferToUint8Array = (reply: RedisResponseBuffer): Uint8Array => new Uint8Array(reply.data)
110+
const bufferToUTF8 = (reply: RedisResponseBuffer): string => decoder.decode(bufferToUint8Array(reply))
110111

111112
const UintArrayToString = (reply: UintArray): string => decoder.decode(new Uint8Array(reply))
112113

@@ -138,7 +139,7 @@ const hexToBuffer = (data: string): RedisResponseBuffer => {
138139
}
139140

140141
const bufferToJava = (reply: RedisResponseBuffer) => {
141-
const stream = new ObjectInputStream(new Uint8Array(reply.data))
142+
const stream = new ObjectInputStream(bufferToUint8Array(reply))
142143
const decoded = stream.readObject()
143144
const { fields } = decoded
144145
const fieldsArray = Array.from(fields, ([key, value]) => ({ [key]: value }))
@@ -172,6 +173,7 @@ export {
172173
ASCIIToBuffer,
173174
isEqualBuffers,
174175
stringToBuffer,
176+
bufferToUint8Array,
175177
bufferToString,
176178
UintArrayToString,
177179
hexToBuffer,

redisinsight/ui/src/utils/tests/decompressors/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,6 @@ export const SNAPPY_COMPRESSED_VALUE_2 = [1, 0, 50]
2121

2222
export const BROTLI_COMPRESSED_VALUE_1 = [49, 65, 76, 231, 187, 141, 68]
2323
export const BROTLI_COMPRESSED_VALUE_2 = [49, 65, 76, 231, 191, 141, 68]
24+
25+
export const PHPGZCOMPRESS_COMPRESSED_VALUE_1 = [120, 156, 51, 4, 0, 0, 50, 0, 50]
26+
export const PHPGZCOMPRESS_COMPRESSED_VALUE_2 = [120, 156, 51, 2, 0, 0, 51, 0, 51]

redisinsight/ui/src/utils/tests/decompressors/decompressors.spec.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import {
1818
SNAPPY_COMPRESSED_VALUE_1,
1919
BROTLI_COMPRESSED_VALUE_1,
2020
BROTLI_COMPRESSED_VALUE_2,
21+
PHPGZCOMPRESS_COMPRESSED_VALUE_1,
22+
PHPGZCOMPRESS_COMPRESSED_VALUE_2,
2123
} from './constants'
2224

2325
const defaultValues = [
@@ -129,6 +131,22 @@ const defaultValues = [
129131
outputStr: DECOMPRESSED_VALUE_STR_2,
130132
isCompressed: true,
131133
},
134+
{
135+
input: PHPGZCOMPRESS_COMPRESSED_VALUE_1,
136+
compressor: KeyValueCompressor.PHPGZCompress,
137+
compressorInit: KeyValueCompressor.PHPGZCompress,
138+
output: DECOMPRESSED_VALUE_1,
139+
outputStr: DECOMPRESSED_VALUE_STR_1,
140+
isCompressed: true,
141+
},
142+
{
143+
input: PHPGZCOMPRESS_COMPRESSED_VALUE_2,
144+
compressor: KeyValueCompressor.PHPGZCompress,
145+
compressorInit: KeyValueCompressor.PHPGZCompress,
146+
output: DECOMPRESSED_VALUE_2,
147+
outputStr: DECOMPRESSED_VALUE_STR_2,
148+
isCompressed: true,
149+
},
132150
].map((value) => ({
133151
...value,
134152
input: anyToBuffer(value.input)
@@ -139,7 +157,10 @@ describe('getCompressor', () => {
139157
let expected = compressorByValue || compressor
140158

141159
// SNAPPY doesn't have magic symbols
142-
if (compressor === KeyValueCompressor.SNAPPY || compressor === KeyValueCompressor.Brotli) {
160+
if (compressor === KeyValueCompressor.SNAPPY
161+
|| compressor === KeyValueCompressor.Brotli
162+
|| compressor === KeyValueCompressor.PHPGZCompress
163+
) {
143164
expected = null
144165
}
145166

redisinsight/ui/src/utils/tests/formatters/bufferFormatters.spec.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import {
1111
bufferToHex,
1212
bufferToBinary,
1313
binaryToBuffer,
14-
bufferToJava
14+
bufferToJava,
15+
bufferToUint8Array,
1516
} from 'uiSrc/utils'
1617

1718
const defaultValues = [
@@ -141,3 +142,9 @@ describe('bufferToJava', () => {
141142
expect(bufferToJava(input)).toEqual(expected)
142143
})
143144
})
145+
146+
describe('bufferToUint8Array', () => {
147+
test.each(javaValues)('%o', ({ uint8Array }) => {
148+
expect(bufferToUint8Array(anyToBuffer(uint8Array))).toEqual(new Uint8Array(uint8Array))
149+
})
150+
})

yarn.lock

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2674,6 +2674,11 @@
26742674
resolved "https://registry.yarnpkg.com/@types/numeral/-/numeral-0.0.28.tgz#e43928f0bda10b169b6f7ecf99e3ddf836b8ebe4"
26752675
integrity sha512-Sjsy10w6XFHDktJJdXzBJmoondAKW+LcGpRFH+9+zXEDj0cOH8BxJuZA9vUDSMAzU1YRJlsPKmZEEiTYDlICLw==
26762676

2677+
"@types/pako@^2.0.0":
2678+
version "2.0.0"
2679+
resolved "https://registry.yarnpkg.com/@types/pako/-/pako-2.0.0.tgz#12ab4c19107528452e73ac99132c875ccd43bdfb"
2680+
integrity sha512-10+iaz93qR5WYxTo+PMifD5TSxiOtdRaxBf7INGGXMQgTCu8Z/7GYWYFUOS3q/G0nE5boj1r4FEB+WSy7s5gbA==
2681+
26772682
"@types/parse-json@^4.0.0":
26782683
version "4.0.0"
26792684
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
@@ -7637,6 +7642,11 @@ fengari@^0.1.4:
76377642
sprintf-js "^1.1.1"
76387643
tmp "^0.0.33"
76397644

7645+
fflate@^0.7.4:
7646+
version "0.7.4"
7647+
resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.7.4.tgz#61587e5d958fdabb5a9368a302c25363f4f69f50"
7648+
integrity sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==
7649+
76407650
figures@^3.0.0, figures@^3.2.0:
76417651
version "3.2.0"
76427652
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
@@ -12390,6 +12400,11 @@ p-try@^2.0.0:
1239012400
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
1239112401
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
1239212402

12403+
pako@^2.1.0:
12404+
version "2.1.0"
12405+
resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86"
12406+
integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==
12407+
1239312408
pako@~1.0.2, pako@~1.0.5:
1239412409
version "1.0.11"
1239512410
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"

0 commit comments

Comments
 (0)