Changeset View
Changeset View
Standalone View
Standalone View
src/xsprintf/qsprintf.php
| Show All 26 Lines | |||||
| * tests for characters outside of the basic multilingual plane. | * tests for characters outside of the basic multilingual plane. | ||||
| * | * | ||||
| * %C, %LC ("Column") | * %C, %LC ("Column") | ||||
| * Escapes a column name or a list of column names. | * Escapes a column name or a list of column names. | ||||
| * | * | ||||
| * %K ("Comment") | * %K ("Comment") | ||||
| * Escapes a comment. | * Escapes a comment. | ||||
| * | * | ||||
| * %Q ("Query Fragment") | * %Q, %LA, %LO, %LQ ("Query Fragment") | ||||
| * Injects a query fragment from a prior call to qsprintf(). | * Injects a query fragment from a prior call to qsprintf(). The list | ||||
| * variants join a list of query fragments with AND, OR, or comma. | |||||
| * | * | ||||
| * %R ("Database and Table Reference") | * %R ("Database and Table Reference") | ||||
| * Behaves like "%T.%T" and prints a full reference to a table including | * Behaves like "%T.%T" and prints a full reference to a table including | ||||
| * the database. Accepts a AphrontDatabaseTableRefInterface. | * the database. Accepts a AphrontDatabaseTableRefInterface. | ||||
| * | * | ||||
| * %P ("Password or Secret") | * %P ("Password or Secret") | ||||
| * Behaves like "%s", but shows "********" when the query is printed in | * Behaves like "%s", but shows "********" when the query is printed in | ||||
| * logs or traces. Accepts a PhutilOpaqueEnvelope. | * logs or traces. Accepts a PhutilOpaqueEnvelope. | ||||
| ▲ Show 20 Lines • Show All 127 Lines • ▼ Show 20 Lines | case 'L': // List of.. | ||||
| $value = implode(', ', $value); | $value = implode(', ', $value); | ||||
| break; | break; | ||||
| case 'C': // ...columns. | case 'C': // ...columns. | ||||
| foreach ($value as $k => $v) { | foreach ($value as $k => $v) { | ||||
| $value[$k] = $escaper->escapeColumnName($v); | $value[$k] = $escaper->escapeColumnName($v); | ||||
| } | } | ||||
| $value = implode(', ', $value); | $value = implode(', ', $value); | ||||
| break; | break; | ||||
| case 'Q': | |||||
| foreach ($value as $k => $v) { | |||||
| $value[$k] = $v->getUnmaskedString(); | |||||
| } | |||||
| $value = implode(', ', $value); | |||||
| break; | |||||
| case 'O': | |||||
| foreach ($value as $k => $v) { | |||||
| $value[$k] = $v->getUnmaskedString(); | |||||
| } | |||||
| $value = '(('.implode(') OR (', $value).'))'; | |||||
| break; | |||||
| case 'A': | |||||
| foreach ($value as $k => $v) { | |||||
| $value[$k] = $v->getUnmaskedString(); | |||||
| } | |||||
| $value = '(('.implode(') AND (', $value).'))'; | |||||
| break; | |||||
| default: | default: | ||||
| throw new XsprintfUnknownConversionException("%L{$next}"); | throw new XsprintfUnknownConversionException("%L{$next}"); | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| if (!$done) { | if (!$done) { | ||||
| qsprintf_check_type($value, $type, $pattern); | qsprintf_check_type($value, $type, $pattern); | ||||
| ▲ Show 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | |||||
| function qsprintf_check_type($value, $type, $query) { | function qsprintf_check_type($value, $type, $query) { | ||||
| switch ($type) { | switch ($type) { | ||||
| case 'Ld': | case 'Ld': | ||||
| case 'Ls': | case 'Ls': | ||||
| case 'LC': | case 'LC': | ||||
| case 'LB': | case 'LB': | ||||
| case 'Lf': | case 'Lf': | ||||
| case 'LQ': | |||||
| case 'LA': | |||||
| case 'LO': | |||||
| if (!is_array($value)) { | if (!is_array($value)) { | ||||
| throw new AphrontParameterQueryException( | throw new AphrontParameterQueryException( | ||||
| $query, | $query, | ||||
| pht('Expected array argument for %%%s conversion.', $type)); | pht('Expected array argument for %%%s conversion.', $type)); | ||||
| } | } | ||||
| if (empty($value)) { | if (empty($value)) { | ||||
| throw new AphrontParameterQueryException( | throw new AphrontParameterQueryException( | ||||
| $query, | $query, | ||||
| pht('Array for %%%s conversion is empty.', $type)); | pht('Array for %%%s conversion is empty.', $type)); | ||||
| } | } | ||||
| foreach ($value as $scalar) { | foreach ($value as $scalar) { | ||||
| qsprintf_check_scalar_type($scalar, $type, $query); | qsprintf_check_scalar_type($scalar, $type, $query); | ||||
| } | } | ||||
| break; | break; | ||||
| default: | default: | ||||
| qsprintf_check_scalar_type($value, $type, $query); | qsprintf_check_scalar_type($value, $type, $query); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| function qsprintf_check_scalar_type($value, $type, $query) { | function qsprintf_check_scalar_type($value, $type, $query) { | ||||
| switch ($type) { | switch ($type) { | ||||
| case 'LQ': | |||||
| case 'LA': | |||||
| case 'LO': | |||||
| if (!($value instanceof PhutilQueryString)) { | |||||
| throw new AphrontParameterQueryException( | |||||
| $query, | |||||
| pht( | |||||
| 'Expected a list of PhutilQueryString objects for %%%s '. | |||||
| 'conversion.', | |||||
| $type)); | |||||
| } | |||||
| break; | |||||
| case 'Q': | case 'Q': | ||||
| // TODO: See T13217. Remove this eventually. | // TODO: See T13217. Remove this eventually. | ||||
| if (is_string($value)) { | if (is_string($value)) { | ||||
| phlog( | phlog( | ||||
| pht( | pht( | ||||
| 'UNSAFE: Raw string ("%s") passed to query ("%s") for "%%Q" '. | 'UNSAFE: Raw string ("%s") passed to query ("%s") for "%%Q" '. | ||||
| 'conversion. %%Q should be passed a query string.', | 'conversion. %%Q should be passed a query string.', | ||||
| $value, | $value, | ||||
| ▲ Show 20 Lines • Show All 71 Lines • Show Last 20 Lines | |||||