/** * Pode ser chamado diretamente por um throw ou quando o PHP dispara um erro (WARNING, PARSE ou FATAL). * No segundo caso um próprio método erro() dessa clase dispara a exceção. * * @param String $message Texto descritivo sobre o que pode ter acontecido na rotina que disparou o erro. * @param int $gravidade Valor inteiro para indicar a gravidade (0 a 3) da exceção. No caso de ser disparada por um * erro do PHP esse campo é um valor constante que indica qual tipo de erro. * @param array $contexto Array com valores do debug_backtrace() (nativo do PHP), pode não ser enviado ou ignorado * com valor false. No caso de erros no PHP tráz informações sobre linha, arquivo e contexto (veja doc * set_error_handler) * @param bool $erro_php É usado apenas pelo método erro() da classe para indicar que não é uma exceção do sistema, * mas sim um erro no PHP. O método erro() está sendo usado como handle dos erros no PHP para que os * usuários não vejam mensagens de erros. * @return void */ public function __construct($message, $gravidade = __CLASS__, $contexto = false, $erro_php = false) { if (!self::$identificador_execucao) { self::$identificador_execucao = str_pad(rand(1, 9999), 4, '0', STR_PAD_LEFT); } $this->message = $message; $this->erro_nome = self::$identificador_execucao . '-' . ++self::$cont_erros . '-' . $gravidade . "-" . date('Y-m-d-H-i-s') . ".json"; $this->erros['level'] = $gravidade; $this->erros['datetime'] = date("H:i:s Y-m-d", time()); $this->erros['mensagem'] = $message; $this->erros['db_error'] = DB::error(); if ($erro_php) { $erro_linha = $contexto['linha']; $erro_arquivo = $contexto['arquivo']; $message = strip_tags($message); /* * Não sei porque diabos esta chave as vezes vem com valores recursivos infinitos que causam erro no * sistema. */ $contexto['contexto']["GLOBALS"] = " "; // muitas vezes o erro do php não traz o debug_backtrace $contexto['Backtrace'] = debug_backtrace(); } else { $erro_linha = self::getLine(); $erro_arquivo = self::getFile(); if (SYS_MODO_DEVEL) { echo "<pre><br /><b>{$gravidade}</b> {$message}\n\nno arquivo {$erro_arquivo} Linha: {$erro_linha}<br /><br /></pre>"; } } $this->id_unico = basename($erro_arquivo, '.php') . '.' . $erro_linha; $this->erros['PHP']['Arquivo'] = $erro_arquivo; $this->erros['PHP']['Linha'] = $erro_linha; $this->erros['PHP']['Codigo'] = $this->id_unico; /* * Caso tenha sido passado um array com o contexto do erro/exceção. */ if ($contexto) { $this->erros['Contexto'] = $contexto; } else { $this->erros['Backtrace'] = debug_backtrace(); } $this->erros["GET"] = $_GET; $this->erros["POST"] = $_POST; $this->erros["REQUEST"] = $_REQUEST; if (isset($_SESSION)) { $this->erros["Sessao"] = $_SESSION; } $this->erros["Cookies"] = $_COOKIE; $this->erros["Arquivos"] = $_FILES; $this->erros["Servidor"] = $_SERVER; $this->erros["APPS"] = (array) System::getInstance(); foreach (SysDebug::getErros() as $err) { $this->erros['user_erros'][] = ['Label' => $err['Label'], 'VAR' => $err['VAR'], 'file' => $err['file'], 'line' => $err['line'], 'stringy' => $err['stringy']]; } $json = utf8_decode(json_encode($this->erros, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); $tam_file = file_put_contents(PATH_LOG_ERRO . $this->erro_nome, $json); if (SYS_MODO_DEVEL) { echo "<br/>Erro: " . $this->erro_nome; echo "<br/><pre>{$json}</pre>"; } /* * Verifica se o sistema está configurado para enviar um e-mail para o administrador com o json. */ if (ERROS_ENVIAR_EMAIL && !self::$erro_pai_enviado) { $largura_coluna = 20; $msg = '<code><pre>' . SYS_NAME . " Disse:\n" . $message; $msg .= "\n\n" . str_pad('Arquivo: ', $largura_coluna) . $erro_arquivo; $msg .= "\n" . str_pad('Codigo: ', $largura_coluna) . $this->id_unico; $msg .= "\n" . str_pad('Linha: ', $largura_coluna) . $erro_linha; $msg .= "\n" . str_pad('Erro banco: ', $largura_coluna) . DB::error(); $msg .= "\n----------------------------------------------------------------------------------\n"; $msg .= "\n" . str_pad("Horario:", $largura_coluna) . date('H:i:s d/m/Y'); if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) { $msg .= "\n" . str_pad("IP:", $largura_coluna) . $_SERVER['HTTP_X_FORWARDED_FOR']; $msg .= "\n" . str_pad("Proxy:", $largura_coluna) . '<a href="http://www.geoiptool.com/?IP=' . $_SERVER['REMOTE_ADDR'] . '" target="_blank">' . $_SERVER['REMOTE_ADDR'] . '</a>'; } else { $msg .= "\n" . str_pad("IP:", $largura_coluna) . '<a href="http://www.geoiptool.com/?IP=' . $_SERVER['REMOTE_ADDR'] . '" target="_blank">' . $_SERVER['REMOTE_ADDR'] . '</a>'; } $msg .= "\n" . str_pad("Navegador:", $largura_coluna) . $_SERVER['HTTP_USER_AGENT']; $msg .= "\n" . str_pad("URL requisitada:", $largura_coluna) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; $msg .= "\n" . str_pad("POST:", $largura_coluna) . count($_POST); $msg .= "\n" . str_pad("GET:", $largura_coluna) . count($_GET); $msg .= "\n" . str_pad("FILES:", $largura_coluna) . count($_FILES); $msg .= "\n" . str_pad("URL raiz:", $largura_coluna) . URL_ROOT; $msg .= "\n\n\n" . str_pad("JSON", $largura_coluna) . $json; if ($tam_file) { $msg .= "\n----------------------------------------------------------------------------------\n"; $msg .= "\n" . str_pad("Arquivo em:", $largura_coluna) . PATH_LOG_ERRO . $this->erro_nome; } else { $msg .= "\n\nNÃO FOI POSSÍVEL ESCREVER O ARQUIVO EM DISCO!"; } $msg .= "</pre></code>"; if (ERROS_ANEXAR) { $anexo_codificado = chunk_split(base64_encode($json)); $mailheaders = "\nMIME-version: 1.0\n"; $mailheaders .= "Content-type: multipart/mixed; "; $mailheaders .= "boundary=\"Message-Boundary\"\n"; $mailheaders .= "Content-transfer-encoding: 7BIT\n"; $mailheaders .= "X-attachments: {$this->erro_nome}"; $body_top = "--Message-Boundary\n"; $body_top .= "Content-type: text/html; charset=utf8\n"; $body_top .= "Content-transfer-encoding: 7BIT\n"; $body_top .= "Content-description: Mail message body\n\n"; $msg = $body_top . $msg; $msg .= "\n\n--Message-Boundary\n"; $msg .= "Content-type: application/json; name=\"{$this->erro_nome}\"\n"; $msg .= "Content-Transfer-Encoding: BASE64\n"; $msg .= "Content-disposition: attachment; filename=\"{$this->erro_nome}\"\n\n"; $msg .= "{$anexo_codificado}\n"; $msg .= "--Message-Boundary--\n"; } $mailheaders .= "\nReferences: <" . $this->id_unico . "@" . parse_url(URL_ROOT, PHP_URL_HOST) . ">\n"; $msg .= "\n\nAtt, " . SYS_NAME . " (" . SIS_EMAIL . ")"; $assunto = "[" . $gravidade . "][" . str_replace("http://", '', URL_ROOT) . '] ' . utf8_decode(substr($this->id_unico, 0, 30)); if (mail(ERROS_EMAIL, $assunto, $msg, "From: " . SYS_NAME . " <" . SIS_EMAIL . ">" . $mailheaders)) { self::$erro_pai_enviado = true; } else { file_put_contents(PATH_LOG_ERRO . "EMAIL_{$this->erro_nome}", "Erro ao enviar e-mail do erro {$this->erro_nome}"); } } }