Passed
Push — main ( 893379...c57f14 )
by Thierry
02:07
created

QueryInputTrait::processInput()   B

Complexity

Conditions 9
Paths 8

Size

Total Lines 27
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 9
eloc 18
c 1
b 0
f 0
nc 8
nop 2
dl 0
loc 27
rs 8.0555
1
<?php
2
3
namespace Lagdo\DbAdmin\Db\Traits;
4
5
use Lagdo\DbAdmin\Driver\Entity\TableFieldEntity;
6
7
use function file_get_contents;
8
use function substr;
9
use function function_exists;
10
use function iconv;
11
use function json_decode;
12
use function is_array;
13
use function preg_match;
14
15
trait QueryInputTrait
16
{
17
    /**
18
     * @param array $file
19
     * @param string $key
20
     * @param bool $decompress
21
     *
22
     * @return string
23
     */
24
    private function readFileContent(array $file, string $key, bool $decompress): string
25
    {
26
        $name = $file['name'][$key];
27
        $tmpName = $file['tmp_name'][$key];
28
        $content = file_get_contents($decompress && preg_match('~\.gz$~', $name) ?
29
            "compress.zlib://$tmpName" : $tmpName); //! may not be reachable because of open_basedir
30
        if (!$decompress) {
31
            return $content;
32
        }
33
        $start = substr($content, 0, 3);
34
        if (function_exists('iconv') && preg_match("~^\xFE\xFF|^\xFF\xFE~", $start, $regs)) {
35
            // not ternary operator to save memory
36
            return iconv('utf-16', 'utf-8', $content) . "\n\n";
37
        }
38
        if ($start == "\xEF\xBB\xBF") { // UTF-8 BOM
39
            return substr($content, 3) . "\n\n";
40
        }
41
        return $content;
42
    }
43
44
    /**
45
     * Get file contents from $_FILES
46
     *
47
     * @param string $key
48
     * @param bool $decompress
49
     *
50
     * @return string|null
51
     */
52
    private function getFileContents(string $key, bool $decompress = false)
53
    {
54
        $file = $_FILES[$key];
55
        if (!$file) {
56
            return null;
57
        }
58
        foreach ($file as $key => $val) {
59
            $file[$key] = (array) $val;
60
        }
61
        $queries = '';
62
        foreach ($file['error'] as $key => $error) {
63
            if (($error)) {
64
                return $error;
65
            }
66
            $queries .= $this->readFileContent($file, $key, $decompress);
67
        }
68
        //! Support SQL files not ending with semicolon
69
        return $queries;
70
    }
71
72
    /**
73
     * @param TableFieldEntity $field
74
     * @param string $value
75
     * @param string $function
76
     *
77
     * @return string
78
     */
79
    private function getInputFieldExpression(TableFieldEntity $field, string $value, string $function): string
80
    {
81
        $expression = $this->driver->quote($value);
82
        if (preg_match('~^(now|getdate|uuid)$~', $function)) {
83
            return "$function()";
84
        }
85
        if (preg_match('~^current_(date|timestamp)$~', $function)) {
86
            return $function;
87
        }
88
        if (preg_match('~^([+-]|\|\|)$~', $function)) {
89
            return $this->driver->escapeId($field->name) . " $function $expression";
90
        }
91
        if (preg_match('~^[+-] interval$~', $function)) {
92
            return $this->driver->escapeId($field->name) . " $function " .
93
                (preg_match("~^(\\d+|'[0-9.: -]') [A-Z_]+\$~i", $value) ? $value : $expression);
94
        }
95
        if (preg_match('~^(addtime|subtime|concat)$~', $function)) {
96
            return "$function(" . $this->driver->escapeId($field->name) . ", $expression)";
97
        }
98
        if (preg_match('~^(md5|sha1|password|encrypt)$~', $function)) {
99
            return "$function($expression)";
100
        }
101
        return $expression;
102
    }
103
104
    /**
105
     * @param TableFieldEntity $field Single field from fields()
106
     * @param string $value
107
     * @param string $function
108
     *
109
     * @return string
110
     */
111
    protected function getUnconvertedFieldValue(TableFieldEntity $field, string $value, string $function = ''): string
112
    {
113
        if ($function === 'SQL') {
114
            return $value; // SQL injection
115
        }
116
        $expression = $this->getInputFieldExpression($field, $value, $function);
117
        return $this->driver->unconvertField($field, $expression);
118
    }
119
120
    /**
121
     * @param mixed $value
122
     *
123
     * @return false|int|string
124
     */
125
    private function getEnumFieldValue($value)
126
    {
127
        if ($value === -1) {
128
            return false;
129
        }
130
        if ($value === '') {
131
            return 'NULL';
132
        }
133
        return +$value;
134
    }
135
136
    /**
137
     * @param TableFieldEntity $field
138
     *
139
     * @return string|false
140
     */
141
    private function getOrigFieldValue(TableFieldEntity $field)
142
    {
143
        if (preg_match('~^CURRENT_TIMESTAMP~i', $field->onUpdate) === false) {
144
            return false;
145
        }
146
        return $this->driver->escapeId($field->name);
147
    }
148
149
    /**
150
     * @param mixed $value
151
     *
152
     * @return array|false
153
     */
154
    private function getJsonFieldValue($value)
155
    {
156
        if (!is_array($value = json_decode($value, true))) {
157
            return false; //! Report errors
158
        }
159
        return $value;
160
    }
161
}
162