This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
1 | <?php declare(strict_types=1); |
||||
2 | |||||
3 | namespace XoopsModules\Xhelp; |
||||
4 | |||||
5 | /* |
||||
6 | * You may not change or alter any portion of this comment or credits |
||||
7 | * of supporting developers from this source code or any supporting source code |
||||
8 | * which is considered copyrighted (c) material of the original comment or credit authors. |
||||
9 | * |
||||
10 | * This program is distributed in the hope that it will be useful, |
||||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||||
13 | */ |
||||
14 | |||||
15 | /** |
||||
16 | * @copyright {@link https://xoops.org/ XOOPS Project} |
||||
17 | * @license {@link https://www.gnu.org/licenses/gpl-2.0.html GNU GPL 2 or later} |
||||
18 | * @author Brian Wahoff <[email protected]> |
||||
19 | * @author XOOPS Development Team |
||||
20 | */ |
||||
21 | |||||
22 | if (!\defined('XHELP_CONSTANTS_INCLUDED')) { |
||||
23 | exit(); |
||||
24 | } |
||||
25 | |||||
26 | \define('MD5SIGNATUREPATTERN', '/{([^ ]*)}/i'); |
||||
27 | \define('HEADER_PRIORITY', 'Importance'); |
||||
28 | \define('_XHELP_MSGTYPE_TICKET', 1); |
||||
29 | \define('_XHELP_MSGTYPE_RESPONSE', 2); |
||||
30 | |||||
31 | require_once \XHELP_PEAR_PATH . '/Mail/mimeDecode.php'; |
||||
32 | |||||
33 | /** |
||||
34 | * EmailParser class |
||||
35 | * |
||||
36 | * Part of the email submission subsystem |
||||
37 | * |
||||
38 | * @author Brian Wahoff <[email protected]> |
||||
39 | */ |
||||
40 | class EmailParser |
||||
41 | { |
||||
42 | public $_params = []; |
||||
43 | |||||
44 | /** |
||||
45 | * Class Constructor |
||||
46 | */ |
||||
47 | public function __construct() |
||||
48 | { |
||||
49 | $this->_params['include_bodies'] = true; |
||||
50 | $this->_params['decode_bodies'] = true; |
||||
51 | $this->_params['decode_headers'] = true; |
||||
52 | $this->_params['input'] = ''; |
||||
53 | } |
||||
54 | |||||
55 | /** |
||||
56 | * Parses Message |
||||
57 | * @param array $msg |
||||
58 | * @return ParsedMessage |
||||
59 | */ |
||||
60 | public function &parseMessage(array $msg): ParsedMessage |
||||
61 | { |
||||
62 | $struct = $this->_parseMsg($msg); |
||||
63 | $newMsg = new ParsedMessage($struct); |
||||
64 | |||||
65 | return $newMsg; |
||||
66 | } |
||||
67 | |||||
68 | /** |
||||
69 | * @param array $msg |
||||
70 | * @return array |
||||
71 | */ |
||||
72 | public function &_parseMsg(array $msg): array |
||||
73 | { |
||||
74 | $arr = []; |
||||
75 | //Parse out attachments/HTML |
||||
76 | $this->_params['input'] = $msg['msg']; |
||||
77 | |||||
78 | $structure = Mail_mimeDecode::decode($this->_params); |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
79 | $body = $this->_getBody($structure); |
||||
80 | $arr['hash'] = $this->parseTicketID($structure->headers['subject']); |
||||
81 | $arr['msg'] = $this->_parseBody($body); |
||||
0 ignored issues
–
show
It seems like
$body can also be of type boolean ; however, parameter $msg of XoopsModules\Xhelp\EmailParser::_parseBody() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
82 | $arr['mime_struct'] = $structure; |
||||
83 | $arr = \array_merge($arr, $this->_parseFrom($structure->headers['from'])); |
||||
84 | |||||
85 | return $arr; |
||||
86 | } |
||||
87 | |||||
88 | /** |
||||
89 | * @param string $from |
||||
90 | * @return array |
||||
91 | */ |
||||
92 | public function &_parseFrom(string $from): array |
||||
93 | { |
||||
94 | //Extract Name & Email from supplied message |
||||
95 | //eregi("From: (.*)\nTo:",$headers, $addr); |
||||
96 | \preg_match('/"?([^"<@]*)"?/i', $from, $name); |
||||
97 | //eregi("<(.*)>",$from, $email); |
||||
98 | |||||
99 | $arr['name'] = $name[1]; |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
100 | |||||
101 | $pattern['email'] = "/([a-z0-9\-_\.]+?)@([^, \r\n\"\(\)'<>\[\]]+)/i"; |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
102 | |||||
103 | \preg_match($pattern['email'], $from, $matches); |
||||
104 | $arr['email'] = $matches[0]; |
||||
105 | |||||
106 | //$arr['email'] = $email[1]; |
||||
107 | return $arr; |
||||
108 | } |
||||
109 | |||||
110 | /** |
||||
111 | * @param string $msg |
||||
112 | * @return mixed|string |
||||
113 | */ |
||||
114 | public function parseTicketID(string $msg) |
||||
115 | { |
||||
116 | $matches = []; |
||||
117 | $ret = \preg_match(MD5SIGNATUREPATTERN, $msg, $matches); |
||||
118 | |||||
119 | if ($ret) { |
||||
120 | // This function assumes that the ticket id is stored in the first |
||||
121 | // regex subquery. If the regex needs to be changed, this logic |
||||
122 | // may need to be changed as well. |
||||
123 | return $matches[1]; |
||||
124 | } |
||||
125 | |||||
126 | return ''; |
||||
127 | } |
||||
128 | |||||
129 | /** |
||||
130 | * @param array $msg |
||||
131 | * @return array|string|string[]|null |
||||
132 | */ |
||||
133 | public function _parseBody(array $msg) |
||||
134 | { |
||||
135 | $msg = $this->_quoteBody((string)$msg); |
||||
136 | $msg = $this->_stripMd5Key($msg); |
||||
137 | |||||
138 | return $msg; |
||||
139 | } |
||||
140 | |||||
141 | /** |
||||
142 | * @param string $msg |
||||
143 | * @return string |
||||
144 | */ |
||||
145 | public function _quoteBody(string $msg): string |
||||
146 | { |
||||
147 | $current = 0; |
||||
148 | |||||
149 | $msg = \explode("\r\n", $msg); |
||||
150 | |||||
151 | foreach ($msg as $i => $iValue) { |
||||
152 | $pattern = []; |
||||
153 | $replace = []; |
||||
154 | $next = $current + 1; |
||||
155 | $prev = $current - 1; |
||||
156 | $pattern[0] = '/^(>[\s]?){' . $next . '}(.*)/i'; |
||||
157 | $replace[0] = '[quote]\\2'; |
||||
158 | $pattern[1] = '/^(>[\s]?){' . $current . '}(.*)/i'; |
||||
159 | $replace[1] = '\\2'; |
||||
160 | |||||
161 | $pattern[2] = '/^(>[\s]?){' . $prev . '}(.*)/i'; |
||||
162 | $replace[2] = '[/quote]\\2'; |
||||
163 | |||||
164 | //Check if current line indicates a quote |
||||
165 | if (\preg_match($pattern[0], $iValue)) { |
||||
166 | $msg[$i] = \preg_replace($pattern[0], $replace[0], $iValue); |
||||
167 | ++$current; |
||||
168 | } else { |
||||
169 | if ($current) { |
||||
170 | //Check if line indicates a closed quote |
||||
171 | if (\preg_match($pattern[1], $iValue)) { |
||||
172 | $msg[$i] = \preg_replace($pattern[1], $replace[1], $iValue); |
||||
173 | } else { |
||||
174 | $msg[$i] = \preg_replace($pattern[2], $replace[2], $iValue); |
||||
175 | $current--; |
||||
176 | } |
||||
177 | } |
||||
178 | } |
||||
179 | } |
||||
180 | |||||
181 | return \implode("\r\n", $msg); |
||||
182 | } |
||||
183 | |||||
184 | /** |
||||
185 | * @param string $msg |
||||
186 | * @return array|string|string[]|null |
||||
187 | */ |
||||
188 | public function _stripMd5Key(string $msg) |
||||
189 | { |
||||
190 | $pattern = '/^\*{4}\s' . \_XHELP_TICKET_MD5SIGNATURE . '\s(.)*\*{4}/im'; |
||||
191 | |||||
192 | return \preg_replace($pattern, '', $msg); |
||||
193 | } |
||||
194 | |||||
195 | /** |
||||
196 | * @param object|array $part |
||||
197 | * @param string $primary |
||||
198 | * @param string $secondary |
||||
199 | * @return bool|array |
||||
200 | */ |
||||
201 | public function _getBody($part, string $primary = 'text', string $secondary = 'plain') |
||||
202 | { |
||||
203 | $body = false; |
||||
204 | |||||
205 | // 1. No subparts: |
||||
206 | |||||
207 | // 2. array of subparts |
||||
208 | // 2a. subarray of subparts (recursion)? |
||||
209 | |||||
210 | if (\is_array($part)) { |
||||
211 | foreach ($part as $subpart) { |
||||
212 | if (!$body = $this->_getBody($subpart, $primary, $secondary)) { |
||||
213 | continue; |
||||
214 | } |
||||
215 | |||||
216 | return $body; |
||||
217 | } |
||||
218 | } else { |
||||
219 | if (isset($part->parts)) { |
||||
220 | return $this->_getBody($part->parts, $primary, $secondary); |
||||
221 | } |
||||
222 | if ($part->ctype_primary == $primary && $part->ctype_secondary == $secondary) { |
||||
223 | return $part->body; |
||||
224 | } |
||||
225 | } |
||||
226 | |||||
227 | return $body; |
||||
228 | } |
||||
229 | } |
||||
230 |