'Opn', 'Not a bug' => 'Nab', 'Feedback' => 'Fbk', 'No Feedback' => 'NoF', 'Wont fix' => 'Wfx', 'Duplicate' => 'Dup', 'Critical' => 'Ctl', 'Assigned' => 'Asn', 'Analyzed' => 'Ana', 'Verified' => 'Ver', 'Suspended' => 'Sus', 'Closed' => 'Csd', 'Spam' => 'Spm', 'Re-Opened' => 'ReO', ]; $bug_types = [ 'Bug' => 'Bug', 'Feature/Change Request' => 'Req', 'Documentation Problem' => 'Doc', 'Security' => 'Sec Bug' ]; // Used in show_state_options() $state_types = [ 'Open' => 2, 'Closed' => 2, 'Re-Opened' => 1, 'Duplicate' => 1, 'Critical' => 1, 'Assigned' => 2, 'Not Assigned' => 0, 'Analyzed' => 1, 'Verified' => 1, 'Suspended' => 1, 'Wont fix' => 1, 'No Feedback' => 1, 'Feedback' => 1, 'Old Feedback' => 0, 'Stale' => 0, 'Fresh' => 0, 'Not a bug' => 1, 'Spam' => 1, 'All' => 0, ]; /** * Authentication */ function verify_user_password($user, $pass) { global $errors; $post = http_build_query( [ 'token' => getenv('AUTH_TOKEN'), 'username' => $user, 'password' => $pass, ] ); $opts = [ 'method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $post, ]; $ctx = stream_context_create(['http' => $opts]); $s = file_get_contents('https://main.php.net/fetch/cvsauth.php', false, $ctx); $a = @unserialize($s); if (!is_array($a)) { $errors[] = "Failed to get authentication information.\nMaybe master is down?\n"; return false; } if (isset($a['errno'])) { $errors[] = "Authentication failed: {$a['errstr']}\n"; return false; } $_SESSION["user"] = $user; return true; } function bugs_has_access ($bug_id, $bug, $pw, $user_flags) { global $auth_user; if ($bug['private'] != 'Y') { return true; } // When the bug is private, only the submitter, trusted devs, security devs and assigned dev // should see the report info if ($user_flags & (BUGS_SECURITY_DEV | BUGS_TRUSTED_DEV)) { // trusted and security dev return true; } else if (($user_flags == BUGS_NORMAL_USER) && $pw != '' && verify_bug_passwd($bug_id, bugs_get_hash($pw))) { // The submitter return true; } else if (($user_flags & BUGS_DEV_USER) && $bug['reporter_name'] != '' && strtolower($bug['reporter_name']) == strtolower($auth_user->handle)) { // The submitter (php developer) return true; } else if (($user_flags & BUGS_DEV_USER) && $bug['assign'] != '' && strtolower($bug['assign']) == strtolower($auth_user->handle)) { // The assigned dev return true; } return false; } function bugs_authenticate (&$user, &$pw, &$logged_in, &$user_flags) { global $auth_user, $ROOT_DIR; // Default values $user = ''; $pw = ''; $logged_in = false; $user_flags = BUGS_NORMAL_USER; // Set username and password if (!empty($_POST['pw'])) { if (empty($_POST['user'])) { $user = ''; } else { $user = htmlspecialchars($_POST['user']); } $user = strtolower($user); $pw = $_POST['pw']; } elseif (isset($auth_user) && is_object($auth_user) && $auth_user->handle) { $user = $auth_user->handle; $pw = $auth_user->password; } // Authentication and user level check // User levels are: reader (0), commenter/patcher/etc. (edit = 3), submitter (edit = 2), developer (edit = 1) if (!empty($_SESSION["user"])) { $user = $_SESSION["user"]; $user_flags = BUGS_DEV_USER; $logged_in = 'developer'; $auth_user = new stdClass; $auth_user->handle = $user; $auth_user->email = "{$user}@php.net"; $auth_user->name = $user; } elseif ($user != '' && $pw != '' && verify_user_password($user, $pw)) { $user_flags = BUGS_DEV_USER; $logged_in = 'developer'; $auth_user = new stdClass; $auth_user->handle = $user; $auth_user->email = "{$user}@php.net"; $auth_user->name = $user; } else { $auth_user = new stdClass; $auth_user->email = isset($_POST['in']['email']) ? $_POST['in']['email'] : ''; $auth_user->handle = ''; $auth_user->name = ''; } // Check if developer is trusted if ($logged_in == 'developer') { require_once "{$ROOT_DIR}/include/trusted-devs.php"; if (in_array(strtolower($user), $trusted_developers)) { $user_flags |= BUGS_TRUSTED_DEV; } if (in_array(strtolower($user), $security_developers)) { $user_flags |= BUGS_SECURITY_DEV; } } } /* Primitive check for SPAM. Add more later. */ function is_spam($string) { // @php.net users are given permission to spam... we gotta eat! See also bug #48126 if (!empty($GLOBALS['auth_user']->handle)) { return false; } if (preg_match_all('/https?:\/\/(\S+)/', $string, $matches)) { foreach ($matches[1] as $match) { if (!preg_match('/^[^\/)]*(php\.net|github\.com)/', $match)) { return "Due to large amounts of spam, only links to php.net and github.com (including subdomains like gist.github.com) are allowed."; } } } $keywords = [ 'spy', 'bdsm', 'massage', 'mortage', 'sex', '11nong', 'oxycontin', 'distance-education', 'sismatech', 'justiceplan', 'prednisolone', 'baclofen', 'diflucan', 'unbra.se', 'objectis', 'angosso', 'colchicine', 'zovirax', 'korsbest', 'coachbags', 'chaneljpoutlet', '\/Members\/', 'michaelkorsshop', 'mkmichaelkors', 'Burberrysale4u', 'gadboisphotos', 'oakleysunglasseslol', 'partydressuk', 'leslunettesdesoleil', 'PaulRGuthrie', '[a-z]*?fuck[a-z]*?', 'jerseys', 'wholesale', 'fashionretailshop01', 'amoxicillin', 'helpdeskaustralia', 'porn', 'aarinkaur', 'lildurk', 'tvfun', ]; if (preg_match('/\b('. implode('|', $keywords) . ')\b/i', $string)) { return "Comment contains spam word, consider rewording."; } return false; } /* Primitive check for SPAMmy user. Add more later. */ function is_spam_user($email) { if (preg_match("/(rhsoft|reindl|phpbugreports|bugreprtsz|bugreports\d*@gmail|training365)/i", $email)) { return true; } return false; } /** * Obfuscates email addresses to hinder spammer's spiders * * Turns "@" into character entities that get interpreted as "at" and * turns "." into character entities that get interpreted as "dot". * * @param string $txt the email address to be obfuscated * @param string $format how the output will be displayed ('html', 'text', 'reverse') * * @return string the altered email address */ function spam_protect($txt, $format = 'html') { /* php.net addresses are not protected! */ if (preg_match('/^(.+)@php\.net$/i', $txt)) { return $txt; } if ($format == 'html') { $translate = [ '@' => ' at ', '.' => ' dot ', ]; } else { $translate = [ '@' => ' at ', '.' => ' dot ', ]; if ($format == 'reverse') { $translate = array_flip($translate); } } return strtr($txt, $translate); } /** * Goes through each variable submitted and returns the value * from the first variable which has a non-empty value * * Handy function for when you're dealing with user input or a default. * * @param mixed as many variables as you wish to check * * @return mixed the value, if any * * @see field(), txfield() */ function oneof() { foreach (func_get_args() as $arg) { if ($arg) { return $arg; } } } /** * Returns the data from the field requested and sanitizes * it for use as HTML * * If the data from a form submission exists, that is used. * But if that's not there, the info is obtained from the database. * * @param string $n the name of the field to be looked for * * @return mixed the data requested * * @see oneof(), txfield() */ function field($n) { return oneof(isset($_POST['in']) ? htmlspecialchars(isset($_POST['in'][$n]) ? $_POST['in'][$n] : '') : null, htmlspecialchars($GLOBALS['bug'][$n] ?? '')); } /** * Escape string so it can be used as HTML * * @param string $in the string to be sanitized * * @return string the sanitized string * * @see txfield() */ function clean($in) { return mb_encode_numericentity($in, [ 0x0, 0x8, 0, 0xffffff, 0xb, 0xc, 0, 0xffffff, 0xe, 0x1f, 0, 0xffffff, 0x22, 0x22, 0, 0xffffff, 0x26, 0x27, 0, 0xffffff, 0x3c, 0x3c, 0, 0xffffff, 0x3e, 0x3e, 0, 0xffffff, 0x7f, 0x84, 0, 0xffffff, 0x86, 0x9f, 0, 0xffffff, 0xfdd0, 0xfdef, 0, 0xffffff, 0x1fffe, 0x1ffff, 0, 0xffffff, 0x2fffe, 0x2ffff, 0, 0xffffff, 0x3fffe, 0x3ffff, 0, 0xffffff, 0x4fffe, 0x4ffff, 0, 0xffffff, 0x5fffe, 0x5ffff, 0, 0xffffff, 0x6fffe, 0x6ffff, 0, 0xffffff, 0x7fffe, 0x7ffff, 0, 0xffffff, 0x8fffe, 0x8ffff, 0, 0xffffff, 0x9fffe, 0x9ffff, 0, 0xffffff, 0xafffe, 0xaffff, 0, 0xffffff, 0xbfffe, 0xbffff, 0, 0xffffff, 0xcfffe, 0xcffff, 0, 0xffffff, 0xdfffe, 0xdffff, 0, 0xffffff, 0xefffe, 0xeffff, 0, 0xffffff, 0xffffe, 0xfffff, 0, 0xffffff, 0x10fffe, 0x10ffff, 0, 0xffffff, ], 'UTF-8'); } /** * Returns the data from the field requested and sanitizes * it for use as plain text * * If the data from a form submission exists, that is used. * But if that's not there, the info is obtained from the database. * * @param string $n the name of the field to be looked for * * @return mixed the data requested * * @see clean() */ function txfield($n, $bug = null, $in = null) { $one = (isset($in) && isset($in[$n])) ? $in[$n] : false; if ($one) { return $one; } $two = (isset($bug) && isset($bug[$n])) ? $bug[$n] : false; if ($two) { return $two; } } /** * Prints age \n"; } echo '\n"; } /** * Prints bug type '."\n"; } else { echo ''."\n"; } break; case 'No Feedback': echo ''."\n"; break; default: echo ''.$state.''."\n"; break; } /* Allow state 'Closed' always when current state is not 'Not a bug' */ if ($state != 'Not a bug') { echo ''."\n"; } } else { foreach($state_types as $type => $mode) { if (($state == 'Closed' && $type == 'Open') || ($state == 'Open' && $type == 'Re-Opened')) { continue; } if ($mode >= $user_mode) { echo '$type\n"; } } } } /** * Prints bug resolution ' , "\n"; foreach($versions as $v) { echo '' , htmlspecialchars($v) , "\n"; if ($current == $v) { $use++; } } if (!$use && $current) { echo '\n"; } echo '', "\n"; } /** * Prints package name