| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  | /****************************************************************************** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  |  * Wikipedia Account Creation Assistance tool                                 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  |  *                                                                            * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  |  * All code in this file is released into the public domain by the ACC        * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  |  * Development Team. Please see team.json for a list of contributors.         * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  |  ******************************************************************************/ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  | namespace Waca\Pages; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  | use Waca\DataObjects\User; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | use Waca\Tasks\InternalPageBase; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  | use Waca\WebRequest; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  | class PageErrorLogViewer extends InternalPageBase | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  |      * @inheritDoc | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 19 |  |  |      */ | 
            
                                                                        
                            
            
                                    
            
            
                | 20 |  |  |     protected function main() | 
            
                                                                        
                            
            
                                    
            
            
                | 21 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 22 |  |  |         $user = User::getCurrent($this->getDatabase()); | 
            
                                                                        
                            
            
                                    
            
            
                | 23 |  |  |         $this->assign('canView', $this->barrierTest('view', $user)); | 
            
                                                                        
                            
            
                                    
            
            
                | 24 |  |  |         $this->assign('canRemove', $this->barrierTest('remove', $user)); | 
            
                                                                        
                            
            
                                    
            
            
                | 25 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 26 |  |  |         // Get the list of exception logs from the error log directory | 
            
                                                                        
                            
            
                                    
            
            
                | 27 |  |  |         $errorLogDirectory = $this->getSiteConfiguration()->getErrorLog(); | 
            
                                                                        
                            
            
                                    
            
            
                | 28 |  |  |         $files = scandir($errorLogDirectory); | 
            
                                                                        
                            
            
                                    
            
            
                | 29 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 30 |  |  |         // Exclude the files we know should be there | 
            
                                                                        
                            
            
                                    
            
            
                | 31 |  |  |         $filteredFiles = array_filter($files, function($file) { | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                        
                            
            
                                    
            
            
                | 32 |  |  |             return !in_array($file, ['.', '..', 'README.md']); | 
            
                                                                        
                            
            
                                    
            
            
                | 33 |  |  |         }); | 
            
                                                                        
                            
            
                                    
            
            
                | 34 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 35 |  |  |         $exceptionDetails = array_map(function($item) use ($errorLogDirectory) { | 
            
                                                                        
                            
            
                                    
            
            
                | 36 |  |  |             $filename = realpath($errorLogDirectory) . DIRECTORY_SEPARATOR . $item; | 
            
                                                                        
                            
            
                                    
            
            
                | 37 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 38 |  |  |             return [ | 
            
                                                                        
                            
            
                                    
            
            
                | 39 |  |  |                 'id'   => str_replace('.log', '', $item), | 
            
                                                                        
                            
            
                                    
            
            
                | 40 |  |  |                 'date' => date('Y-m-d H:i:s', filemtime($filename)), | 
            
                                                                        
                            
            
                                    
            
            
                | 41 |  |  |                 'data' => str_replace($this->getSiteConfiguration()->getFilePath(), '.', | 
            
                                                                        
                            
            
                                    
            
            
                | 42 |  |  |                     unserialize(file_get_contents($filename))), | 
            
                                                                        
                            
            
                                    
            
            
                | 43 |  |  |             ]; | 
            
                                                                        
                            
            
                                    
            
            
                | 44 |  |  |         }, $filteredFiles); | 
            
                                                                        
                            
            
                                    
            
            
                | 45 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 46 |  |  |         $this->assign('exceptionEntries', $exceptionDetails); | 
            
                                                                        
                            
            
                                    
            
            
                | 47 |  |  |         $this->setTemplate('errorlog/main.tpl'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  |     protected function view() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |         $requestedErrorId = WebRequest::getString('id'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |         $safeFilename = $this->safetyCheck($requestedErrorId); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |         if ($safeFilename === false) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |             $this->redirect('errorLog'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |             return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |         // note: at this point we've done sufficient sanity checks that we can be confident this value is safe to echo | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  |         // back to the user. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |         $this->assign('id', $requestedErrorId); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |         $this->assign('date', date('Y-m-d H:i:s', filemtime($safeFilename))); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |         $data = unserialize(file_get_contents($safeFilename)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |         $this->assign('server', $data['server']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |         $this->assign('get', $data['get']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |         $this->assign('post', $data['post']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |         $exceptionList = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |         $current = $data; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |         do { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |             $ex = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |                 'exception' => $current['exception'], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |                 'message'   => str_replace($this->getSiteConfiguration()->getFilePath(), '.', $current['message']), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |                 'stack'     => str_replace($this->getSiteConfiguration()->getFilePath(), '.', $current['stack']), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |             ]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |             $exceptionList[] = $ex; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |             $current = $current['previous']; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |         while ($current !== null); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |         $this->assign('exceptionList', $exceptionList); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |         $this->setTemplate('errorlog/details.tpl'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |     public function remove() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |         $safeFilename = $this->safetyCheck(WebRequest::getString('id')); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |         if ($safeFilename === false) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |             $this->redirect('errorLog'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |             return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |         unlink($safeFilename); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |         $this->redirect('errorLog'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |         return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |      * @param string|null $requestedErrorId | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |      * @return bool|string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |     protected function safetyCheck(?string $requestedErrorId) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |         if ($requestedErrorId === null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |             return false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |         // security - only allow hex-encoded filenames, as this is what is generated. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |         // This is prefixed with the configured directory. Path traversal is protected against due to . and / not being | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |         // part of the hex character set. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |         if (!preg_match('/^[a-f0-9]{40}$/', $requestedErrorId)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |             return false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |         $errorLogDirectory = $this->getSiteConfiguration()->getErrorLog(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |         $filename = realpath($errorLogDirectory) . DIRECTORY_SEPARATOR . $requestedErrorId . '.log'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  |         if (!file_exists($filename)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |             return false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |         return $filename; | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 133 |  |  |     } | 
            
                                                        
            
                                    
            
            
                | 134 |  |  | } |