Summary: Starting with a new instance running PHP 8.2, address all exceptions that come up through some basic browsing/usage. For `strlen(null)` issues I generally tried to resolve if the value should be non-null at the point of issue, and attempt to address at earlier call-site. There were not many of these that I could determine. In the rest of those cases I would replace with a null-and-strlen check, or use `phutil_nonempty_string` if I was certain the value was a string and it was more convenient. Hitting all code-paths is challenging, so I would search for `strlen` within radius of files I was modifying and evaluate to address those uses in the same manner. Notes: - `AphrontRequest::getStr` only ever returns a string, and is safe to use `phutil_nonempty_string`. - `PhabricatorEnv::getEnvConfig` can return non-string things so any values coming from there should never use `phutil_nonempty_string`. - `AphrontRequest::getHTTPHeader` indicates it could return wild so `phutil_nonempty_string` should not be used. - `AphrontRequest::getURIData` isn't clear if it could return non-string data, so never use `phutil_nonempty_string`. Refs T13588 Test Plan: I'm running an instance on 8.2 and went through the basic setup/installation, startup and usage, including setup issues and configurations/settings. Reviewers: #blessed_reviewers, epriestley Reviewed By: #blessed_reviewers, epriestley Subscribers: aklapper, Korvin, epriestley Maniphest Tasks: T13588 Differential Revision: https://secure.phabricator.com/D21862
145 lines
4.2 KiB
PHP
145 lines
4.2 KiB
PHP
<?php
|
|
|
|
function javelin_tag(
|
|
$tag,
|
|
array $attributes = array(),
|
|
$content = null) {
|
|
|
|
if (isset($attributes['sigil']) ||
|
|
isset($attributes['meta']) ||
|
|
isset($attributes['mustcapture'])) {
|
|
foreach ($attributes as $k => $v) {
|
|
switch ($k) {
|
|
case 'sigil':
|
|
if ($v !== null) {
|
|
$attributes['data-sigil'] = $v;
|
|
}
|
|
unset($attributes[$k]);
|
|
break;
|
|
case 'meta':
|
|
if ($v !== null) {
|
|
$response = CelerityAPI::getStaticResourceResponse();
|
|
$id = $response->addMetadata($v);
|
|
$attributes['data-meta'] = $id;
|
|
}
|
|
unset($attributes[$k]);
|
|
break;
|
|
case 'mustcapture':
|
|
if ($v) {
|
|
$attributes['data-mustcapture'] = '1';
|
|
} else {
|
|
unset($attributes['data-mustcapture']);
|
|
}
|
|
unset($attributes[$k]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isset($attributes['aural'])) {
|
|
if ($attributes['aural']) {
|
|
$class = idx($attributes, 'class', '');
|
|
$class = rtrim('aural-only '.$class);
|
|
$attributes['class'] = $class;
|
|
} else {
|
|
$class = idx($attributes, 'class', '');
|
|
$class = rtrim('visual-only '.$class);
|
|
$attributes['class'] = $class;
|
|
$attributes['aria-hidden'] = 'true';
|
|
}
|
|
unset($attributes['aural']);
|
|
}
|
|
|
|
if (isset($attributes['print'])) {
|
|
if ($attributes['print']) {
|
|
$class = idx($attributes, 'class', '');
|
|
$class = rtrim('print-only '.$class);
|
|
$attributes['class'] = $class;
|
|
|
|
// NOTE: Alternative print content is hidden from screen readers.
|
|
$attributes['aria-hidden'] = 'true';
|
|
} else {
|
|
$class = idx($attributes, 'class', '');
|
|
$class = rtrim('screen-only '.$class);
|
|
$attributes['class'] = $class;
|
|
}
|
|
unset($attributes['print']);
|
|
}
|
|
|
|
|
|
return phutil_tag($tag, $attributes, $content);
|
|
}
|
|
|
|
function phabricator_form(PhabricatorUser $user, $attributes, $content) {
|
|
$body = array();
|
|
|
|
$http_method = idx($attributes, 'method');
|
|
$is_post = (strcasecmp($http_method, 'POST') === 0);
|
|
|
|
$http_action = idx($attributes, 'action');
|
|
$is_absolute_uri = false;
|
|
if ($http_action != null) {
|
|
$is_absolute_uri = preg_match('#^(https?:|//)#', $http_action);
|
|
}
|
|
|
|
if ($is_post) {
|
|
|
|
// NOTE: We only include CSRF tokens if a URI is a local URI on the same
|
|
// domain. This is an important security feature and prevents forms which
|
|
// submit to foreign sites from leaking CSRF tokens.
|
|
|
|
// In some cases, we may construct a fully-qualified local URI. For example,
|
|
// we can construct these for download links, depending on configuration.
|
|
|
|
// These forms do not receive CSRF tokens, even though they safely could.
|
|
// This can be confusing, if you're developing for Phabricator and
|
|
// manage to construct a local form with a fully-qualified URI, since it
|
|
// won't get CSRF tokens and you'll get an exception at the other end of
|
|
// the request which is a bit disconnected from the actual root cause.
|
|
|
|
// However, this is rare, and there are reasonable cases where this
|
|
// construction occurs legitimately, and the simplest fix is to omit CSRF
|
|
// tokens for these URIs in all cases. The error message you receive also
|
|
// gives you some hints as to this potential source of error.
|
|
|
|
if (!$is_absolute_uri) {
|
|
$body[] = phutil_tag(
|
|
'input',
|
|
array(
|
|
'type' => 'hidden',
|
|
'name' => AphrontRequest::getCSRFTokenName(),
|
|
'value' => $user->getCSRFToken(),
|
|
));
|
|
|
|
$body[] = phutil_tag(
|
|
'input',
|
|
array(
|
|
'type' => 'hidden',
|
|
'name' => '__form__',
|
|
'value' => true,
|
|
));
|
|
|
|
// If the profiler was active for this request, keep it active for any
|
|
// forms submitted from this page.
|
|
if (DarkConsoleXHProfPluginAPI::isProfilerRequested()) {
|
|
$body[] = phutil_tag(
|
|
'input',
|
|
array(
|
|
'type' => 'hidden',
|
|
'name' => '__profile__',
|
|
'value' => true,
|
|
));
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (is_array($content)) {
|
|
$body = array_merge($body, $content);
|
|
} else {
|
|
$body[] = $content;
|
|
}
|
|
|
|
return javelin_tag('form', $attributes, $body);
|
|
}
|