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.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * ajaxfileedit.php - backend upload attachments and update file info |
||
4 | * |
||
5 | * @copyright Copyright © 2013 geekwright, LLC. All rights reserved. |
||
6 | * @license gwiki/docs/license.txt GNU General Public License (GPL) |
||
7 | * @since 1.0 |
||
8 | * @author Richard Griffith <[email protected]> |
||
9 | * @package gwiki |
||
10 | */ |
||
11 | include __DIR__ . '/../../mainfile.php'; |
||
12 | $xoopsLogger->activated = false; |
||
13 | // provide error logging for our sanity in debugging ajax use (won't see xoops logger) |
||
14 | restore_error_handler(); |
||
15 | error_reporting(-1); |
||
16 | |||
17 | $dir = basename(__DIR__); |
||
18 | require_once XOOPS_ROOT_PATH . '/modules/' . $dir . '/class/GwikiPage.php'; |
||
19 | global $wikiPage; |
||
20 | $wikiPage = new GwikiPage; |
||
21 | |||
22 | $uploadpath = XOOPS_ROOT_PATH . "/uploads/{$dir}/"; |
||
23 | $uploadurl = XOOPS_URL . "/uploads/{$dir}/"; |
||
24 | |||
25 | $newfile = (isset($_SERVER['HTTP_GW_FILENAME']) ? $_SERVER['HTTP_GW_FILENAME'] : false); |
||
26 | $jsondata = (isset($_SERVER['HTTP_GW_JSONDATA']) ? $_SERVER['HTTP_GW_JSONDATA'] : false); |
||
27 | |||
28 | // initialize whitelist |
||
29 | $whitelist = array(); |
||
30 | $wlconfig = $xoopsModuleConfig['attach_ext_whitelist']; |
||
31 | //$wlconfig='txt,pdf,doc,docx,xls,rtf,zip'; |
||
32 | |||
33 | // populate whitelist |
||
34 | if (!empty($wlconfig)) { |
||
35 | $whitelist = explode(',', $wlconfig); |
||
36 | } |
||
37 | |||
38 | /** |
||
39 | * @param $filename |
||
40 | * |
||
41 | * @return array|bool |
||
42 | */ |
||
43 | function getExtensionInfo($filename) |
||
44 | { |
||
45 | global $whitelist; |
||
46 | |||
47 | $fi = array(); |
||
48 | |||
49 | // these choices are just from our icon set - nothing magic, just ext => filename - .png |
||
50 | $icons = array( |
||
51 | 'aac' => 'aac', |
||
52 | 'aiff' => 'aiff', |
||
53 | 'ai' => 'ai', |
||
54 | 'avi' => 'avi', |
||
55 | 'bmp' => 'bmp', |
||
56 | 'c' => 'c', |
||
57 | 'cpp' => 'cpp', |
||
58 | 'css' => 'css', |
||
59 | 'dat' => 'dat', |
||
60 | 'dmg' => 'dmg', |
||
61 | 'doc' => 'doc', |
||
62 | 'docx' => 'doc', |
||
63 | 'dot' => 'dotx', |
||
64 | 'dotx' => 'dotx', |
||
65 | 'dwg' => 'dwg', |
||
66 | 'dxf' => 'dxf', |
||
67 | 'eps' => 'eps', |
||
68 | 'exe' => 'exe', |
||
69 | 'flv' => 'flv', |
||
70 | 'gif' => 'gif', |
||
71 | 'h' => 'h', |
||
72 | 'hpp' => 'hpp', |
||
73 | 'htm' => 'html', |
||
74 | 'html' => 'html', |
||
75 | 'ics' => 'ics', |
||
76 | 'iso' => 'iso', |
||
77 | 'java' => 'java', |
||
78 | 'jpe' => 'jpg', |
||
79 | 'jpeg' => 'jpg', |
||
80 | 'jpg' => 'jpg', |
||
81 | 'key' => 'key', |
||
82 | 'mid' => 'mid', |
||
83 | 'mp3' => 'mp3', |
||
84 | 'mp4' => 'mp4', |
||
85 | 'mpg' => 'mpg', |
||
86 | 'odf' => 'odf', |
||
87 | 'ods' => 'ods', |
||
88 | 'odt' => 'odt', |
||
89 | 'otp' => 'otp', |
||
90 | 'ots' => 'ots', |
||
91 | 'ott' => 'ott', |
||
92 | 'pdf' => 'pdf', |
||
93 | 'php' => 'php', |
||
94 | 'png' => 'png', |
||
95 | 'ppt' => 'ppt', |
||
96 | 'psd' => 'psd', |
||
97 | 'py' => 'py', |
||
98 | 'qt' => 'qt', |
||
99 | 'rar' => 'rar', |
||
100 | 'rb' => 'rb', |
||
101 | 'rtf' => 'rtf', |
||
102 | 'sql' => 'sql', |
||
103 | 'tga' => 'tga', |
||
104 | 'tgz' => 'tgz', |
||
105 | 'tif' => 'tiff', |
||
106 | 'tiff' => 'tiff', |
||
107 | 'txt' => 'txt', |
||
108 | 'wav' => 'wav', |
||
109 | 'xls' => 'xls', |
||
110 | 'xlsx' => 'xlsx', |
||
111 | 'xml' => 'xml', |
||
112 | 'yml' => 'yml', |
||
113 | 'zip' => 'zip', |
||
114 | ); |
||
115 | // Also have files '_blank' '_page' |
||
116 | |||
117 | $path_parts = pathinfo($filename); |
||
118 | // =$path_parts['dirname'], "\n"; |
||
119 | $fi['file_name'] = $path_parts['basename']; |
||
120 | if (!isset($path_parts['extension'])) { |
||
121 | $ext = ''; |
||
122 | } else { |
||
123 | $ext = strtolower($path_parts['extension']); |
||
124 | } |
||
125 | //=$path_parts['filename']; |
||
126 | |||
127 | // if no name, or not on whitelist reject |
||
128 | if (empty($path_parts['filename']) || array_search($ext, $whitelist) === false) { |
||
129 | return false; |
||
130 | } |
||
131 | |||
132 | if (empty($ext)) { |
||
133 | $fi['file_icon'] = '_blank'; |
||
134 | } else { |
||
135 | if (empty($icons[$ext])) { |
||
136 | $fi['file_icon'] = '_blank'; |
||
137 | } else { |
||
138 | $fi['file_icon'] = $icons[$ext]; |
||
139 | } |
||
140 | } |
||
141 | |||
142 | return $fi; |
||
143 | } |
||
144 | |||
145 | /** |
||
146 | * @param $filename |
||
147 | * |
||
148 | * @return array |
||
149 | */ |
||
150 | function getFileInfo($filename) |
||
151 | { |
||
152 | $fi = array(); |
||
153 | |||
154 | if (function_exists('finfo_open')) { |
||
155 | $finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension |
||
156 | $fi['file_type'] = finfo_file($finfo, $filename); |
||
157 | finfo_close($finfo); |
||
158 | } else { |
||
159 | $fi['file_type'] = mime_content_type($filename); |
||
160 | } |
||
161 | $fi['file_size'] = filesize($filename); |
||
162 | |||
163 | return $fi; |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * @param $string |
||
168 | * |
||
169 | * @return string |
||
170 | */ |
||
171 | View Code Duplication | function cleaner($string) |
|
172 | { |
||
173 | $string = stripcslashes($string); |
||
174 | $string = html_entity_decode($string); |
||
175 | $string = strip_tags($string); // DANGER -- kills wiki text |
||
176 | $string = trim($string); |
||
177 | $string = stripslashes($string); |
||
178 | |||
179 | return $string; |
||
180 | } |
||
181 | |||
182 | /** |
||
183 | * @param $uid |
||
184 | * |
||
185 | * @return string |
||
186 | */ |
||
187 | function getUserName($uid) |
||
188 | { |
||
189 | global $xoopsConfig; |
||
190 | |||
191 | $uid = (int)$uid; |
||
192 | |||
193 | if ($uid > 0) { |
||
194 | $memberHandler = xoops_getHandler('member'); |
||
195 | $user = $memberHandler->getUser($uid); |
||
196 | if (is_object($user)) { |
||
197 | return "<a href=\"" . XOOPS_URL . "/userinfo.php?uid=$uid\">" . htmlspecialchars($user->getVar('uname'), ENT_QUOTES) . '</a>'; |
||
198 | } |
||
199 | } |
||
200 | |||
201 | return $xoopsConfig['anonymous']; |
||
202 | } |
||
203 | |||
204 | /** |
||
205 | * @param $input |
||
206 | * |
||
207 | * @return mixed |
||
208 | */ |
||
209 | View Code Duplication | function deleteData(&$input) |
|
210 | { |
||
211 | global $xoopsDB, $uploadpath, $wikiPage; |
||
212 | |||
213 | $q_file_id = (int)$input['file_id']; |
||
214 | // use keyword in delete so we know id and edit authority are connected |
||
215 | $q_keyword = $wikiPage->escapeForDB($input['page']); |
||
216 | |||
217 | // look up the name and delete the image file |
||
218 | $sql = 'SELECT file_path FROM ' . $xoopsDB->prefix('gwiki_page_files') . " where file_id='{$q_file_id}' AND keyword = '{$q_keyword}' "; |
||
219 | |||
220 | $result = $xoopsDB->query($sql); |
||
221 | if ($result) { |
||
222 | $rows = $xoopsDB->getRowsNum($result); |
||
223 | if ($rows) { |
||
224 | $myrow = $xoopsDB->fetchArray($result); |
||
225 | if (!empty($myrow['file_path'])) { |
||
226 | $oldfilename = $uploadpath . '/' . $myrow['file_path']; |
||
227 | unlink($oldfilename); |
||
228 | } |
||
229 | } |
||
230 | } |
||
231 | |||
232 | // delete the row |
||
233 | $sql = 'DELETE FROM ' . $xoopsDB->prefix('gwiki_page_files') . " where file_id='{$q_file_id}' AND keyword = '{$q_keyword}' "; |
||
234 | |||
235 | $result = $xoopsDB->queryF($sql); |
||
236 | $cnt = $xoopsDB->getAffectedRows(); |
||
237 | if ($cnt) { |
||
238 | $input['message'] = _MD_GWIKI_AJAX_FILEEDIT_DEL_OK; |
||
239 | } |
||
240 | |||
241 | return $result; |
||
242 | } |
||
243 | |||
244 | /** |
||
245 | * @param $input |
||
246 | * |
||
247 | * @return mixed |
||
248 | */ |
||
249 | function updateData(&$input) |
||
250 | { |
||
251 | global $xoopsDB, $xoopsUser, $wikiPage; |
||
252 | |||
253 | $q_file_id = (int)$input['file_id']; |
||
254 | $q_keyword = $wikiPage->escapeForDB($input['page']); |
||
255 | $q_file_name = $wikiPage->escapeForDB($input['file_name']); |
||
256 | $q_file_icon = $wikiPage->escapeForDB($input['file_icon']); |
||
257 | $q_file_type = $wikiPage->escapeForDB($input['file_type']); |
||
258 | $q_file_description = $wikiPage->escapeForDB($input['file_description']); |
||
259 | // file_path only changed by image upload |
||
260 | $q_file_size = (int)$input['file_size']; |
||
261 | $q_file_path = empty($input['file_path']) ? '' : $wikiPage->escapeForDB($input['file_path']); |
||
262 | $q_file_uid = $xoopsUser ? $xoopsUser->getVar('uid') : 0; |
||
263 | $input['file_uid'] = $q_file_uid; |
||
264 | if ((int)$input['file_upload_date'] === 0) { |
||
265 | $input['file_upload_date'] = time(); |
||
266 | } |
||
267 | $q_file_upload_date = $input['file_upload_date']; |
||
268 | |||
269 | $sql = 'UPDATE ' . $xoopsDB->prefix('gwiki_page_files') . ' SET '; |
||
270 | $sql .= " file_name = '{$q_file_name}', "; |
||
271 | $sql .= " file_icon = '{$q_file_icon}', "; |
||
272 | $sql .= " file_type = '{$q_file_type}', "; |
||
273 | $sql .= " file_size = '{$q_file_size}', "; |
||
274 | $sql .= " file_path = '{$q_file_path}', "; |
||
275 | $sql .= " file_uid = '{$q_file_uid}', "; |
||
276 | // $sql.= " file_uid = '{$q_file_upload_date}', "; |
||
277 | $sql .= " file_description = '{$q_file_description}' "; |
||
278 | $sql .= " where file_id = '{$q_file_id}' AND keyword = '{$q_keyword}' "; |
||
279 | |||
280 | $result = $xoopsDB->queryF($sql); |
||
281 | if (!$result) { |
||
282 | header('Status: 500 Internal Error - Database Error'); |
||
283 | $out['message'] === $xoopsDB->error(); |
||
0 ignored issues
–
show
|
|||
284 | echo json_encode($out); |
||
285 | exit; |
||
286 | } |
||
287 | $cnt = $xoopsDB->getAffectedRows(); |
||
288 | if (!$cnt) { |
||
289 | $input['message'] = _MD_GWIKI_AJAX_FILEEDIT_NOT_DEFINED; |
||
290 | } else { |
||
291 | $input['message'] = _MD_GWIKI_AJAX_FILEEDIT_UPD_OK; |
||
292 | } |
||
293 | |||
294 | //file_id, keyword, file_name, file_path, file_type, file_icon, file_size, file_upload_date, file_description, file_uid |
||
295 | |||
296 | if ($result && !$cnt && !empty($q_file_path)) { // database is OK but nothing to update - require file_path |
||
297 | $sql = 'insert into ' . $xoopsDB->prefix('gwiki_page_files'); |
||
298 | $sql .= ' (keyword, file_name, file_path, file_type, file_icon, file_size, file_upload_date, file_description, file_uid) '; |
||
299 | $sql .= " values ('{$q_keyword}', '{$q_file_name}', '{$q_file_path}', '{$q_file_type}', '{$q_file_icon}', '{$q_file_size}', $q_file_upload_date, '{$q_file_description}', '{$q_file_uid}' )"; |
||
300 | $result = $xoopsDB->queryF($sql); |
||
0 ignored issues
–
show
$result is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
301 | $input['file_id'] = $xoopsDB->getInsertId(); |
||
302 | $input['message'] = _MD_GWIKI_AJAX_FILEEDIT_ADD_OK; |
||
303 | } |
||
304 | |||
305 | return $input['file_id']; |
||
306 | } |
||
307 | |||
308 | /** |
||
309 | * @param $newfile |
||
310 | * @param $input |
||
311 | * |
||
312 | * @return mixed |
||
313 | */ |
||
314 | function updateFile($newfile, &$input) |
||
315 | { |
||
316 | global $uploadpath, $xoopsDB; |
||
317 | // For now, images are stored in individual directories for each page. |
||
318 | // We can change the directory distribution later, as the entire path |
||
319 | // relative to /uploads/gwiki/ ($relpath) is stored in the database. |
||
320 | |||
321 | // We get rid of any colons in the page name in case the filesystem has |
||
322 | // issues with them. (undescore is illegal in page name, so it stays unique.) |
||
323 | $relpath = 'pages/' . str_replace(':', '_', $input['page']) . '/file/'; |
||
324 | $ourpath = $uploadpath . $relpath; |
||
325 | $oldUmask = umask(0); |
||
326 | @mkdir($ourpath, 0755, true); |
||
327 | umask($oldUmask); |
||
328 | $tempfn = tempnam($ourpath, 'WIKIFILE_'); |
||
329 | $image = file_get_contents('php://input'); |
||
330 | file_put_contents($tempfn, $image); |
||
331 | |||
332 | $filename = $ourpath . $newfile; |
||
333 | if (empty($input['file_name'])) { |
||
334 | $input['file_name'] = $justfn; |
||
0 ignored issues
–
show
|
|||
335 | } |
||
336 | |||
337 | $fi = getFileInfo($tempfn); |
||
338 | foreach ($fi as $k => $v) { |
||
339 | $input[$k] = $v; |
||
340 | } |
||
341 | |||
342 | $input['file_name'] = $newfile; |
||
343 | $input['file_path'] = $relpath . $newfile; |
||
344 | |||
345 | rename($tempfn, $filename); |
||
346 | chmod($filename, 0644); |
||
347 | $q_file_id = (int)$input['file_id']; |
||
348 | $sql = 'SELECT file_path FROM ' . $xoopsDB->prefix('gwiki_page_files') . " where file_id='{$q_file_id}' "; |
||
349 | |||
350 | $result = $xoopsDB->query($sql); |
||
351 | if ($result) { |
||
352 | $rows = $xoopsDB->getRowsNum($result); |
||
353 | if ($rows) { |
||
354 | $myrow = $xoopsDB->fetchArray($result); |
||
355 | if (!empty($myrow['file_path'])) { |
||
356 | $oldfilename = $uploadpath . '/' . $myrow['file_path']; |
||
357 | unlink($oldfilename); |
||
358 | } |
||
359 | // update |
||
360 | } else { |
||
361 | // new row |
||
362 | } |
||
363 | } |
||
364 | $input['file_upload_date'] = time(); |
||
365 | |||
366 | return updateData($input); |
||
367 | } |
||
368 | |||
369 | if (!$jsondata) { |
||
370 | header('Status: 500 Internal Error - No Data Passed'); |
||
371 | exit; |
||
372 | } |
||
373 | $input = json_decode($jsondata, true); |
||
374 | //file_put_contents ( XOOPS_ROOT_PATH.'/uploads/debug.txt', print_r($input,true)); |
||
375 | |||
376 | if (!empty($input['file_id'])) { |
||
377 | $q_file_id = (int)$input['file_id']; |
||
378 | $sql = 'SELECT * FROM ' . $xoopsDB->prefix('gwiki_page_files') . " where file_id = '{$q_file_id}' "; |
||
379 | $result = $xoopsDB->query($sql); |
||
380 | if ($row = $xoopsDB->fetcharray($result)) { |
||
381 | $input['page'] = $row['keyword']; |
||
382 | foreach ($row as $k => $v) { |
||
383 | if (!isset($input[$k])) { |
||
384 | $input[$k] = $v; |
||
385 | } |
||
386 | } |
||
387 | } |
||
388 | } |
||
389 | |||
390 | if (empty($input['page'])) { |
||
391 | header('Status: 500 Internal Error - No Page'); |
||
392 | exit; |
||
393 | } |
||
394 | $input['page'] = strtolower($wikiPage->normalizeKeyword($input['page'])); |
||
395 | $pageX = $wikiPage->getPage($input['page']); |
||
396 | $mayEdit = $wikiPage->checkEdit(); |
||
397 | |||
398 | View Code Duplication | if (!$mayEdit) { |
|
399 | header('Status: 403 Forbidden - No Permission'); |
||
400 | if (!$mayEdit) { |
||
401 | $out['message'] = _MD_GWIKI_AJAX_FILEEDIT_NO_AUTH; |
||
402 | } |
||
403 | echo json_encode($out); |
||
404 | exit; |
||
405 | } |
||
406 | |||
407 | $q_newfile = $wikiPage->escapeForDB($newfile); |
||
408 | $q_keyword = $wikiPage->escapeForDB($input['page']); |
||
409 | |||
410 | $sql = 'SELECT file_id FROM ' . $xoopsDB->prefix('gwiki_page_files') . " where file_name = '{$q_newfile}' AND keyword='{$q_keyword}' "; |
||
411 | |||
412 | $result = $xoopsDB->query($sql); |
||
413 | if ($row = $xoopsDB->fetcharray($result)) { |
||
414 | if ($input['file_id'] !== $row['file_id']) { |
||
415 | header('Status: 500 Internal Error - Duplicate File Name'); |
||
416 | $out['message'] = _MD_GWIKI_AJAX_FILEEDIT_DUPLICATE; |
||
417 | echo json_encode($out); |
||
418 | exit; |
||
419 | } |
||
420 | } |
||
421 | |||
422 | /* |
||
423 | * This creates issues if page being edited has not been saved yet, so let's not be anal about it |
||
424 | if (!$pageX) { |
||
425 | header("Status: 403 Forbidden - No Page"); |
||
426 | if(!$pageX) $out['message']='Page does not exist'; |
||
427 | echo json_encode($out); |
||
428 | exit; |
||
429 | } |
||
430 | */ |
||
431 | |||
432 | if ($newfile) { |
||
433 | $fi = getExtensionInfo($newfile); |
||
434 | if ($fi === false) { |
||
435 | header('Status: 403 Forbidden - Bad File Type'); |
||
436 | $out['message'] = _MD_GWIKI_AJAX_FILEEDIT_BAD_TYPE; |
||
437 | echo json_encode($out); |
||
438 | exit; |
||
439 | } |
||
440 | foreach ($fi as $k => $v) { |
||
441 | $input[$k] = $v; |
||
442 | } |
||
443 | $input['file_id'] = updateFile($newfile, $input); |
||
444 | if ($input['file_id']) { |
||
445 | $input['message'] = 'Attachment Saved'; |
||
446 | $input['link'] = $uploadurl . $input['file_path']; |
||
447 | $input['iconlink'] = XOOPS_URL . '/modules/' . $dir . '/assets/icons/48px/' . $input['file_icon'] . '.png'; |
||
448 | $input['userlink'] = getUserName($input['file_uid']); |
||
449 | $input['size'] = number_format($input['file_size']); |
||
450 | $input['date'] = date($wikiPage->dateFormat, $input['file_upload_date']); |
||
451 | } |
||
452 | View Code Duplication | } else { |
|
453 | if (!empty($input['op']) && $input['op'] === 'delete') { |
||
454 | deleteData($input); |
||
455 | } else { |
||
456 | updateData($input); |
||
457 | } |
||
458 | } |
||
459 | echo json_encode($input); |
||
460 | exit; |
||
461 |
This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.