# All files / src/custom-nodes/self-defending-nodes/group SelfDefendingCustomNodeGroup.ts

97.22% Statements 35/36
75% Branches 3/4
100% Functions 3/3
96.97% Lines 32/33

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    1111x
    1x

    1x

    1x
    1x

    1x
    1x
    1x

    1x

    1812x

    1x

    1812x

    1812x
    1812x

    1809x

    1809x
    1x

    1809x
    1x

    1x

    1x

    1x

    1809x

    1809x
    1808x

    1x

    1x
    1x

    1x
    1x

    1x
    1x

     import { injectable, inject } from 'inversify';
    import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';

    import { TCustomNodeFactory } from '../../../types/container/TCustomNodeFactory';
    import { TObfuscationEvent } from '../../../types/event-emitters/TObfuscationEvent';
    import { TNodeWithBlockStatement } from '../../../types/node/TNodeWithBlockStatement';

    import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
    import { IObfuscationEventEmitter } from '../../../interfaces/event-emitters/IObfuscationEventEmitter';
    import { IOptions } from '../../../interfaces/options/IOptions';
    import { IStackTraceData } from '../../../interfaces/stack-trace-analyzer/IStackTraceData';

    import { initializable } from '../../../decorators/Initializable';

    import { CustomNodes } from '../../../enums/container/CustomNodes';
    import { ObfuscationEvents } from '../../../enums/ObfuscationEvents';

    import { AbstractCustomNodeGroup } from '../../AbstractCustomNodeGroup';
    import { NodeAppender } from '../../../node/NodeAppender';
    import { RandomGeneratorUtils } from '../../../utils/RandomGeneratorUtils';

    @injectable()
    export class SelfDefendingCustomNodeGroup extends AbstractCustomNodeGroup {
        /**
         * @type {TObfuscationEvent}
         */
        protected appendEvent: TObfuscationEvent = ObfuscationEvents.AfterObfuscation;

        /**
         * @type {TCustomNodeFactory}
         */
        private readonly customNodeFactory: TCustomNodeFactory;

        /**
         * @type {Map<CustomNodes, ICustomNode>}
         */
        @initializable()
        protected customNodes: Map <CustomNodes, ICustomNode>;

        /**
         * @type {IObfuscationEventEmitter}
         */
        private readonly obfuscationEventEmitter: IObfuscationEventEmitter;

        /**
         * @param customNodeFactory
         * @param obfuscationEventEmitter
         * @param options
         */
        constructor (
            @inject(ServiceIdentifiers['Factory<ICustomNode>']) customNodeFactory: TCustomNodeFactory,
            @inject(ServiceIdentifiers.IObfuscationEventEmitter) obfuscationEventEmitter: IObfuscationEventEmitter,
            @inject(ServiceIdentifiers.IOptions) options: IOptions
        ) {
            super(options);

            this.customNodeFactory = customNodeFactory;
            this.obfuscationEventEmitter = obfuscationEventEmitter;
        }

        /**
         * @param blockScopeNode
         * @param stackTraceData
         */
        public appendCustomNodes (blockScopeNode: TNodeWithBlockStatement, stackTraceData: IStackTraceData[]): void {
            const randomStackTraceIndex: number = NodeAppender.getRandomStackTraceIndex(stackTraceData.length);

            // selfDefendingUnicodeNode append
            this.appendCustomNodeIfExist(CustomNodes.SelfDefendingUnicodeNode, (customNode: ICustomNode) => {
                NodeAppender.appendNodeToOptimalBlockScope(
                    stackTraceData,
                    blockScopeNode,
                    customNode.getNode(),
                    randomStackTraceIndex
                );
            });

            // nodeCallsControllerFunctionNode append
            this.appendCustomNodeIfExist(CustomNodes.NodeCallsControllerFunctionNode, (customNode: ICustomNode) => {
                let targetBlockScope: TNodeWithBlockStatement;

                Iif (stackTraceData.length) {
                    targetBlockScope = NodeAppender.getOptimalBlockScope(stackTraceData, randomStackTraceIndex, 1);
                } else {
                    targetBlockScope = blockScopeNode;
                }

                NodeAppender.prependNode(targetBlockScope, customNode.getNode());
            });
        }

        public initialize (): void {
            this.customNodes = new Map <CustomNodes, ICustomNode> ();

            if (!this.options.selfDefending) {
                return;
            }

            const callsControllerFunctionName: string = RandomGeneratorUtils.getRandomVariableName();

            const selfDefendingUnicodeNode: ICustomNode = this.customNodeFactory(CustomNodes.SelfDefendingUnicodeNode);
            const nodeCallsControllerFunctionNode: ICustomNode = this.customNodeFactory(CustomNodes.NodeCallsControllerFunctionNode);

            selfDefendingUnicodeNode.initialize(callsControllerFunctionName);
            nodeCallsControllerFunctionNode.initialize(this.appendEvent, callsControllerFunctionName);

            this.customNodes.set(CustomNodes.SelfDefendingUnicodeNode, selfDefendingUnicodeNode);
            this.customNodes.set(CustomNodes.NodeCallsControllerFunctionNode, nodeCallsControllerFunctionNode);
        }
    }