| Age | Commit message (Collapse) | Author |
|
file_get_contents() and file_get_contents_with_max_length() return
Vec<u8> instead of a from_utf8_lossy'd String.
Call sites whose consumer takes a &str still convert lossily and are
marked TODO(bytes).
file_get_contents_with_max_length() now reads at most the requested
number of bytes instead of the whole file.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
The signature took usize, so PHP's negative $start and $length, which
count from the end of the string, could not be expressed. Take i64 and
an optional length, and apply PHP's clamping rules.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
str_contains(), str_starts_with() and str_ends_with() were thin wrappers
over the str methods of the same semantics. Call sites now use
contains()/starts_with()/ends_with() directly.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
These parameters kept the leading underscore they were given while their
function bodies were still todo!(), and the underscore now reads as "this
argument is ignored" for arguments the bodies do use.
Removing the prefix stops it from suppressing four clippy lints, fixed
alongside: one redundant field name, and three `&mut Vec` parameters that
only need a slice.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
doRemove() renames a directory to a random hidden name before emptying
it, and undoes that rename when the final rmdir fails, so a concurrent
process cannot recreate the path mid-removal. It also walks one level at
a time through FilesystemIterator instead of flattening the whole tree,
and lets an inner rmdir failure pass, both as upstream does.
copy() keeps the mode fopen($targetFile, 'w') would have left rather
than the origin's, symlink() and mirror() call readlink() and
getLinkTarget() where upstream does, and a directory iterator that
cannot be opened propagates its UnexpectedValueException instead of
being swallowed or flattened into an IOException.
Error message text is out of scope per docs/known-incompatibilities.md,
so the three TODO(phase-c) markers that only tracked wording are gone,
along with linkException()'s Windows-only branch. So are the arguments
no caller varies -- symlink()'s copyOnWindows, mirror()'s iterator and
options, copy()'s overwriteNewerFiles -- which removes the last
TODO(phase-c) in the file.
New shim functions: readlink, filesystem_iterator, stream_is_local,
strrev and SplFileInfo::getLinkTarget. base64_encode takes bytes so
random_bytes() can feed it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
The shim raises no PHP-level errors, so error_get_last() always returned
None and every message built from it lost its trailing reason. Now that
the fs mutators and php_strip_whitespace carry an io::Error, take the
reason from the call that actually failed instead of a global last-error
slot.
Filesystem::unlinkImplementation returns that error rather than a bool so
ensureDirectoryExists, unlink and rmdir can report it, and PhpFileParser
appends it to the "following message may be helpful" hint. The wording
is Rust's io::Error text, not PHP's warning text, for the same reason
noted in symfony/filesystem.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
|
The shim's filesystem entry points took `&str` even though each one resolves
to a local path through `std::fs` or a syscall, so callers holding a `PathBuf`
had to stringify it at the call site. They now take `impl AsRef<Path>`, the
form `file_exists`, `is_dir`, `unlink` and the rest of the already-converted
set use.
`Phar`, `PharData` and `ZipArchive` keep their archive path as a `PathBuf`.
`PharData::compress` names the compressed sibling by appending the suffix to
the file name rather than formatting the path into a `String`.
Arguments PHP resolves through a stream wrapper (`fopen`, `file_put_contents`,
`include`) still take `&str`, as do the byte-string operations (`dirname`,
`basename`, `pathinfo`) and archive-internal entry names, which are `/`-joined
logical names rather than OS paths.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
mb_check_encoding
http_get_last_response_headers()/http_clear_last_response_headers() now back
a thread-local store with a recording hook for the (still unported) HTTP
stream layer; with no request recorded they return None, matching PHP.
mb_check_encoding gains the trivial ASCII arm; other encodings still need
the mbstring tables and stay todo!().
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
Retag every Shirabe-authored TODO comment to one of the fixed tags:
phase-c, phase-d, plugin, php-runtime, phase-e.
Upstream-authored TODO comments from Composer/Symfony are left
untouched to preserve the ported code shape.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
Rust's &str is always valid UTF-8, so the mbstring/iconv sanitization
chain can never trigger. Reduce it to a no-op with a TODO(phase-c)
marker: once the codebase strictly separates Vec<u8> from String, this
should take &[u8] and convert lossily. This removes the last caller of
the php-shim iconv(), so delete it as well.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
Remove the eight Cursor methods that have no callers, and the sscanf
shim whose only caller was Cursor::get_current_position.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
The only callers were trivial fixed-format uses: reading the first
four hash bytes as a native int, splitting in_addr byte strings, and
building a constant ZIP EOCD record. Each site now does the byte
manipulation directly, so the general-purpose shims are no longer
needed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
%e/%E/%g/%G never appear in Composer's own format strings (verified by
sweeping composer/src and vendor); supporting PHP's exponent formatting
is intentionally out of scope, so fail permanently instead of marking
the specifiers as pending work.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
The audit in .ken/php-shim-copying.md judged 14 functions in
shirabe-php-shim (plus php_wordwrap in shirabe-external-packages) to be
line-by-line transcriptions or structural imitations of php-src. PHP's
relicensing to 3-clause BSD makes keeping them legal, but the boundary
between BSD-derived and MIT code was invisible in the source tree.
Moving them into their own crate puts the license into the build
metadata (so NOTICE generation follows the binary), makes a reverse
dependency a compile error, and encodes the origin in the module path,
which mirrors php-src's ext tree. Each function records its origin in a
fixed-format doc comment, and a new php_src_derivation_boundary linter
fails if `php-src` appears in any Rust source outside the crate.
Public paths under shirabe_php_shim:: are unchanged: functions that are
themselves derived are re-exported with `pub use`, and the wrappers that
only validate arguments stay on the MIT side.
This also resolves the duplicate wordwrap implementation.
shirabe_php_shim::wordwrap was todo!(), so SymfonyStyle::block panicked,
while shirabe-external-packages carried its own copy. Both now go
through the single port, verified against real PHP on 13 cases covering
multi-character breaks and cut.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
diagnose used to read hardcoded shim stubs, so it described a fictional
runtime: OPENSSL_VERSION_NUMBER was always 0 and tripped the TLSv1.1/1.2
check, PHP_BINARY and OPENSSL_VERSION_TEXT were empty, and the extension,
function and ini probes answered from a fixed table.
The PHP worker gained a `diagnose` entry that returns every fact the
command needs as one PHP array, cached in a OnceLock so the several call
sites share a single round trip. Reading it back needed array support in
the serialize() parser, which in turn lets get_loaded_extensions and
get_all_ini_files return real lists instead of comma-joined strings.
Also fixes the openssl_version message, which dropped strstr()'s
before_needle argument during the port, and check_connectivity's
allow_url_fopen test, which did not follow PHP string truthiness.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
The b'>' match arm in strip_tags's state machine never pushed the
character to the output buffer when encountered outside a tag (state
0), unlike every other special-character arm (!, ?, -, and the
catch-all) which does push in that state. Every literal '>' not part
of an HTML-like tag was silently dropped.
This corrupted "=>" into "=" in Composer's operation trace strings
(e.g. "Upgrading foo/bar (1.0.0 => 1.1.0)"), which go through
strip_tags to remove the <info>/<comment> markup before comparison,
un-ignoring 82 integration tests that were asserting on that exact
arrow.
|
|
shirabe_php_shim::chr() returned a Rust String, which lossily
re-encodes bytes >= 0x80 as UTF-8 replacement characters. ip_get_mask,
ip_get_network, and ip_map_to_6 relied on chr() to build raw in_addr
and netmask byte arrays, corrupting IPv4-in-IPv6 mappings and CIDR
netmasks. Build the Vec<u8> byte arrays directly instead of
round-tripping through String, and un-ignore test_ip_address and
test_ip_range now that the underlying bug is fixed.
chr()'s only other caller (http_downloader.rs, an ASCII ESC byte in a
regex pattern) didn't need the indirection either, so remove the shim
function entirely.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
|
|
|
Port autoload_generator (24), bitbucket (14), suggested_packages (11),
git_driver (6), archive_manager (3), and a bump command test. Fix the
ApplicationTester output-capture root cause (php://memory streams must be
readable regardless of fopen mode). Implement posix_getuid/geteuid, the PCRE
'A' anchored modifier, php_strip_whitespace, stream_get_wrappers, is_callable
scalars; fix preg_quote angle-bracket escaping and class-map parser regexes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
Implement the bulk of string.rs shims:
- sprintf() with flags/width/precision/positional args for the common
conversions (s/d/u/b/o/x/X/c/f/F)
- pack()/unpack() for the C/c/n/v/N/V (+ s/S/i/I unpack) format codes
- base64_encode()/base64_decode() (non-strict)
- substr_replace, str_bitand, chr, hexdec, stripcslashes, addcslashes,
number_format (round-half-away-from-zero), uniqid, strip_tags,
html_entity_decode, iconv (UTF-8/ASCII identity)
%e/%E/%g/%G, wordwrap, sscanf, php_strip_whitespace and non-UTF-8 iconv
remain TODO(phase-d) (exact float-exponent/tokenizer/encoding-table
behavior not yet ported). Divergences in ported functions are noted with
TODO(phase-d) comments.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
Implement array_unique, array_splice, array_merge_recursive, krsort,
ksort, asort, sort_with_flags and sort_natural_flag_case, plus the
strnatcmp/strnatcasecmp port they rely on. Drop array_key_last and
array_splice_mixed in favour of existing helpers at the call sites.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
|