448 Commits

Author SHA1 Message Date
Gustavo Lopes
b4d66343e7 Do not build linux binaries on release 2026-03-09 10:59:06 +00:00
Gustavo Lopes
2ef087bd9e Version validation in CI 2026-03-09 10:34:59 +00:00
Gustavo Lopes
d9bc8cd4c5 Merge pull request #26 from remicollet/patch-1
Fix version
2026-03-09 09:59:38 +00:00
Remi Collet
60eaceb6ee Fix version 2026-03-09 07:21:40 +01:00
Gustavo Lopes
b6d9dc8eae Update README.md 2026-03-09 00:26:34 +00:00
Gustavo Lopes
d58737756c Fix release build on 32-bit windows 2026-03-09 00:19:32 +00:00
Gustavo Lopes
b79e6491b5 Prepare 4.3.0 release 2026-03-08 23:54:43 +00:00
Gustavo Lopes
1f1baf4fc1 Fix for 32-bit windows 2026-03-08 23:54:43 +00:00
Gustavo Lopes
4e914be013 .gitignore 2026-03-08 23:07:15 +00:00
Gustavo Lopes
05c8e5e675 Fix warning 2026-03-08 23:07:05 +00:00
Gustavo Lopes
b482f2f156 Add largepage.cpp and motw.cpp to Windows build config
These files implement LargePageAlloc and MarkOfTheWeb classes
respectively, which were causing 13 unresolved external symbols
during the Windows DLL link step.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 21:51:37 +00:00
Gustavo Lopes
4115c69fe2 Fix wrong printf format 2026-03-08 21:48:55 +00:00
Gustavo Lopes
ea74acb27b Remove NM definition. Size of P1 in actually MAXPATHSIZE 2026-03-08 21:48:41 +00:00
Gustavo Lopes
1b6a2a5aa4 Fix windows build 2026-03-08 21:15:48 +00:00
Gustavo Lopes
e5b9669359 Add but don't apply .clang-format 2026-03-08 21:12:54 +00:00
Gustavo Lopes
89ac57cd59 Fix dll.cpp: don't propagate non-fatal ErrHandler errors as failures
unrar 7.2.4 changed RARReadHeaderEx and ProcessFile to return
RarErrorToDll(ErrHandler.GetErrorCode()) on the success path instead of
ERAR_SUCCESS. This caused RARX_CRC errors set during header CRC
validation (which still allows the header to be read successfully) to
propagate as ERAR_BAD_DATA, breaking the entry listing loop for archives
with broken header checksums even when allow_broken is set.

Non-fatal error codes RARX_SUCCESS, RARX_WARNING, and RARX_CRC should
not cause RARReadHeaderEx or ProcessFile to return failure on the success
path; callers detect data integrity issues via BrokenHeader or the list
result separately.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 16:25:08 +00:00
Gustavo Lopes
440d2a14c8 Merge unrar 7.2.4 2026-03-08 15:55:36 +00:00
Gustavo Lopes
a169ed937e Fix build: add largepage.cpp, exclude motw.cpp (Windows-only) for unrar 7.1
unrar 7.1 added largepage.cpp and motw.cpp. Add largepage.cpp to the
build (its LargePageAlloc class is declared without platform guards and
compiled cleanly on Linux with the Windows-only code guarded out).

Exclude motw.cpp because MarkOfTheWeb is only declared when PROPAGATE_MOTW
is set (Windows-only), so motw.cpp cannot compile on Linux.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 15:55:01 +00:00
Gustavo Lopes
10e3e3222a Merge unrar 7.1.5 2026-03-08 15:52:13 +00:00
Gustavo Lopes
055906e455 Fix rarentry.c: zero-initialize RARHeaderDataEx to prevent segfault
The RARHeaderDataEx struct gained ArcNameEx and FileNameEx pointer fields
in unrar 7.0. In rarentry.c the struct was declared on the stack without
initialization, leaving these pointers with garbage values. RARReadHeaderEx
checks if these pointers are non-NULL before writing through them, so it
would follow the garbage pointer and cause a segfault (reproducible in
test 004.phpt).

Fix by zero-initializing the struct at declaration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 15:51:10 +00:00
Gustavo Lopes
2d3b968d23 Update extractchunk.cpp for unrar 7.0 std::wstring API changes
unrar 7.0 converted all path/name variables from wchar arrays to
std::wstring. Update extractchunk.cpp to use the new API:
- ArcName, DestFileName, DllDestName are now std::wstring
- VolNameToFirstName and ConvertPath have new signatures

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 15:44:13 +00:00
Gustavo Lopes
371536d3a8 Fix arccmt.cpp: remove extra brace introduced during 6.2.9 conflict resolution
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 15:43:06 +00:00
Gustavo Lopes
3f536c9f9d Fix os.hpp: restore NM define removed in unrar 7.0
unrar 7.0 removed the NM path-size define from os.hpp, but the PHP
extension code in rar.c still uses it. Add NM back as a compatibility
define with the same value (2048).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 15:42:32 +00:00
Gustavo Lopes
ff2aa63dbf Merge unrar 7.0.9 2026-03-08 15:42:00 +00:00
Gustavo Lopes
0cace1db4b Fix extract.cpp: fix brace mismatch in password check block after 6.2.9 merge
The conflict resolution accidentally closed the while(true) password loop
prematurely. Fix the brace structure so our custom empty-password check
sits inside the loop before the SetEncryption/PswCheck code.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 15:37:38 +00:00
Gustavo Lopes
0c05fac324 Merge unrar 6.2.9 2026-03-08 15:36:33 +00:00
Gustavo Lopes
ae9a4623fe Fix isnt.cpp: wrap Windows-only code in #ifdef _WIN_ALL
isnt.cpp was added in unrar 6.1.5 without platform guards, causing
compilation failure on Linux due to Windows-only headers (comdef.h,
Wbemidl.h). Wrap entire implementation in #ifdef _WIN_ALL to match
the original pattern and rar.hpp include guard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 15:32:39 +00:00
Gustavo Lopes
88773b47f1 Merge unrar 6.1.5 2026-03-08 15:31:20 +00:00
Gustavo Lopes
5e74ad9803 Update unrar_update.md 2026-03-08 15:21:45 +00:00
Gustavo Lopes
f6650b4abe Remove PHP 5 support 2026-03-08 15:11:27 +00:00
Gustavo Lopes
be202cc5b1 Add PHP 8.3 CI support; fix type-error wording in tests
Wire up PHP 8.3 Linux matrix jobs and Justfile targets. Fix three EXPECTF
patterns in tests/002, 003, 008: PHP 8.3 changed the type-error message
wording from "bool given" to "false given", so widen "boo%s" to "%s" to
match both old and new phrasing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 15:11:16 +00:00
Gustavo Lopes
6a2ec1ccfc Add PHP 8.2 CI support; fix __toString arginfo
Wire up PHP 8.2 Linux matrix jobs and Justfile targets. Update Windows CI
to PHP 8.2. Fix the __toString() methods on RarArchive and RarEntry to
declare IS_STRING return type under PHP_VERSION_ID >= 80200 — PHP 8.2
enforces that __toString() has a declared string return type and emits
warnings (breaking tests) without it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 15:10:36 +00:00
Gustavo Lopes
eb1a919fb9 Document php upgrade procedure.
Both debug and release-zts variants pass 109/109 tests under PHP 8.1.
2026-03-08 15:09:46 +00:00
Gustavo Lopes
5e063a9626 Add PHP 8.1 CI support
Wire up PHP 8.1 Linux matrix jobs (debug + release-zts) via Docker image
SHA entries and Justfile targets. Update Windows CI job from PHP 8.0 to 8.1.
No C source changes required for 8.1 compatibility.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 01:14:35 +00:00
Gustavo Lopes
4a4e67ec33 Moderninze run-tests.php; use it on windows CI too 2026-03-02 01:14:35 +00:00
Gustavo Lopes
3dcba946ab Migrate CI from Azure Pipelines/Appveyor to GitHub Actions
Replace the old Azure Pipelines + Appveyor setup with GitHub Actions:
- Add .github/workflows/tests.yml with Linux (matrix) and Windows jobs
- Add .github/scripts/build-and-test.sh (shared build+test script)
- Add .github/scripts/update-docker-shas.sh (Docker image SHA lockfile updater)
- Add .github/docker-image-shas.yml (pinned OCI index digests for Linux jobs)
- Add Justfile for local test targets mirroring CI
- Add unrar_update.md documenting the unrar update process
- Remove azure-pipelines.yml, azure-template.yml, appveyor.yml, appveyor.bat,
  test_funcs.sh
2026-03-01 18:14:32 +00:00
Gustavo Lopes
77cc02a1db Fix RAR5 chunk extraction spurious warning on Windows with multi-core CPUs
On Windows, RAR_SMP is defined and Unpack5MT is used when MaxUserThreads > 1
(i.e. on any multi-core machine). Unlike Unpack5, Unpack5MT does not set
FileExtracted = true on completion, leaving it false after SetDestSize() clears
it. In chunk extraction mode (suspendAfterInit = true), this caused
RARProcessFileChunk to return *finished = false even after writing all data,
triggering a second unnecessary call that wrote 0 bytes and fired the spurious
"Extraction reported as unfinished but no data read" warning.

Fix by skipping Unpack5MT when suspendAfterInit is true, falling through to
Unpack5 which correctly implements the suspend/resume protocol. The existing
comment in DoUnpack already noted that Unpack5MT must not be used in suspended
mode; the condition just wasn't enforced.

Remove the now-stale Appveyor skip from test 101.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-01 17:33:13 +00:00
Gustavo Lopes
0131eef66c Use zend_long in lieu of long where appropriate 2026-03-01 17:33:13 +00:00
Gustavo Lopes
823315f6d6 Added unrar 7.2.4 2026-02-28 01:18:16 +00:00
Gustavo Lopes
40a7872954 Added unrar 7.2.3 2026-02-28 01:18:16 +00:00
Gustavo Lopes
9babd4f983 Added unrar 7.2.2 2026-02-28 01:18:15 +00:00
Gustavo Lopes
366007b41a Added unrar 7.2.1 2026-02-28 01:18:14 +00:00
Gustavo Lopes
320f84b6ae Added unrar 7.1.5 2026-02-28 01:18:14 +00:00
Gustavo Lopes
899eb2cedd Added unrar 7.1.4 2026-02-28 01:18:13 +00:00
Gustavo Lopes
d21e05b1f7 Added unrar 7.1.3 2026-02-28 01:18:12 +00:00
Gustavo Lopes
1c76380291 Added unrar 7.1.2 2026-02-28 01:18:12 +00:00
Gustavo Lopes
55a566364a Added unrar 7.1.1 2026-02-28 01:18:11 +00:00
Gustavo Lopes
5823bb16b5 Added unrar 7.0.9 2026-02-28 01:18:11 +00:00
Gustavo Lopes
9a5d712d99 Added unrar 7.0.8 2026-02-28 01:18:10 +00:00
Gustavo Lopes
95fe328cc2 Added unrar 7.0.7 2026-02-28 01:18:09 +00:00
Gustavo Lopes
0a08604b53 Added unrar 7.0.6 2026-02-28 01:18:09 +00:00
Gustavo Lopes
9f17788011 Added unrar 7.0.5 2026-02-28 01:18:08 +00:00
Gustavo Lopes
a657432560 Added unrar 7.0.4 2026-02-28 01:18:08 +00:00
Gustavo Lopes
abb9fa4632 Added unrar 7.0.3 2026-02-28 01:18:07 +00:00
Gustavo Lopes
b810988366 Added unrar 7.0.2 2026-02-28 01:18:07 +00:00
Gustavo Lopes
294d87a695 Added unrar 7.0.1 2026-02-28 01:18:06 +00:00
Gustavo Lopes
f57721dbb3 Added unrar 6.2.9 2026-02-28 01:18:05 +00:00
Gustavo Lopes
094a536987 Added unrar 6.2.8 2026-02-28 01:18:05 +00:00
Gustavo Lopes
340695bebb Added unrar 6.2.7 2026-02-28 01:18:04 +00:00
Gustavo Lopes
e63362d16a Added unrar 6.2.6 2026-02-28 01:18:03 +00:00
Gustavo Lopes
cc7d8e8c40 Added unrar 6.2.5 2026-02-28 01:18:03 +00:00
Gustavo Lopes
d2b82835c4 Added unrar 6.2.4 2026-02-28 01:18:02 +00:00
Gustavo Lopes
571deeda60 Added unrar 6.2.3 2026-02-28 01:18:02 +00:00
Gustavo Lopes
412c7bf024 Added unrar 6.2.2 2026-02-28 01:18:01 +00:00
Gustavo Lopes
4594bd1cd1 Added unrar 6.1.5 2026-02-28 01:18:00 +00:00
Gustavo Lopes
3fcd7f12fe Added unrar 6.2.1 2026-02-28 01:18:00 +00:00
Gustavo Lopes
efddae46a9 Added unrar 6.1.4 2026-02-28 01:17:59 +00:00
Gustavo Lopes
63a7b8bbbb Added unrar 6.1.3 2026-02-28 01:17:59 +00:00
Gustavo Lopes
d7a5b2c8f0 Added unrar 6.1.2 2026-02-28 01:17:58 +00:00
Gustavo Lopes
2f979b4b64 Added unrar 6.1.1 2026-02-28 01:17:58 +00:00
Gustavo Lopes
0922854405 Added unrar 6.0.7 2026-02-28 01:16:34 +00:00
Gustavo Lopes
b7ec361367 Added unrar 6.0.6 2026-02-28 01:16:33 +00:00
Gustavo Lopes
1502c092f0 Added unrar 6.0.5 2026-02-28 01:16:33 +00:00
Gustavo Lopes
c00e9c1493 Added unrar 6.0.4 2026-02-28 01:16:32 +00:00
Gustavo Lopes
f367a22fe3 Added unrar 6.0.3 2026-02-28 01:16:31 +00:00
Gustavo Lopes
ab26d28575 Fixes for PHP 8.1 2021-08-16 01:28:05 +01:00
Gustavo Lopes
488dd3caaa Release 4.2.0 2020-12-06 19:57:33 +00:00
Gustavo Lopes
1dc896be94 Merge branch 'unrar', with unrar 6.0.2 2020-12-06 19:46:49 +00:00
Gustavo Lopes
36345d004e Added unrar 6.0.2 2020-12-06 19:45:17 +00:00
Gustavo Lopes
8f070c282f Added unrar 6.0.1 2020-12-06 19:45:04 +00:00
Gustavo Lopes
91ed5b09a0 Publish coverage on codecov 2020-12-06 19:38:25 +00:00
Gustavo Lopes
d95cab037b Support PHP 8 2020-12-06 19:18:01 +00:00
Gustavo Lopes
7cff10aa2c Suppress warnings in PHP header files 2020-12-06 19:18:01 +00:00
Gustavo Lopes
5b94797037 Backport PHP8's run-tests.php 2020-12-06 19:18:01 +00:00
Gustavo Lopes
4ff664b2b0 Merge pull request #9 from Alexander1000/remove-never-used
remove never used piece of code
2020-11-25 14:31:21 +00:00
Aleksandr Dankovtsev
2e13165bdb remove never used piece of code 2020-11-23 22:01:33 +03:00
Gustavo Lopes
d0cd509090 Release 4.1.0 2020-10-11 19:18:11 +01:00
Gustavo Lopes
bd65eab735 Compile with -fvisibility=hidden 2020-10-11 19:01:59 +01:00
Gustavo Lopes
45742b94ab Update to unrar 5.9.4 2020-10-11 18:56:44 +01:00
Gustavo Lopes
6545fdd215 Added unrar 5.9.4 2020-10-11 18:54:32 +01:00
Gustavo Lopes
08f8190e49 Added unrar 5.9.3 2020-10-11 18:54:32 +01:00
Gustavo Lopes
095b4cdd58 Fix PHP 7.4 valgrind tests 2020-10-11 18:38:57 +01:00
Gustavo Lopes
da32228c34 The buffer must be at least as big as the window size 2020-10-11 17:30:15 +01:00
Gustavo Lopes
2788a30227 Warn when we read more data than the file's declared size
Last commit changed how data is read for solid files, but this had a
side effect in that the data returned by the unrar lib was no longer
limited to the size of the file, as declared in its header.

Still keep this new behavior, but add a warning when this happens.
2020-10-11 17:30:15 +01:00
Gustavo Lopes
e0c6c97ef0 Fix bug 76592: streaming unpacking of uncompressed files incomplete 2020-10-11 17:30:15 +01:00
Gustavo Lopes
2322542282 Fixup CI 2020-10-01 09:39:56 +01:00
Gustavo Lopes
2b12de7a8f 7.4 fixes 2020-09-28 09:44:36 +01:00
Gustavo Lopes
23430540f1 Travis to Azure 2020-09-28 09:43:30 +01:00
Gustavo Lopes
e3f3ecd1ab Update to unrar 5.9.2 2020-09-27 23:36:29 +01:00
Gustavo Lopes
544f55920a Add unrar 5.9.2 2020-04-29 20:12:36 +01:00
Gustavo Lopes
24b421e0e6 Add unrar 5.9.1 2020-04-29 20:12:36 +01:00
Gustavo Lopes
05a48cbbeb Added unrar 5.8.5 2020-04-29 20:12:36 +01:00
Gustavo Lopes
6d0e583ef9 Added unrar 5.8.4 2020-04-29 20:12:36 +01:00
Gustavo Lopes
714f15cb06 Added unrar 5.8.3 2020-04-29 20:12:36 +01:00
Gustavo Lopes
58bb195ae3 Added unrar 5.8.2 2020-04-29 20:12:36 +01:00
Gustavo Lopes
5293a8f07e Added unrar 5.8.1 2020-04-29 20:12:36 +01:00
Gustavo Lopes
61edb08973 Added unrar 5.7.5 2020-04-29 20:12:36 +01:00
Gustavo Lopes
adc9fe7d39 Added unrar 5.7.4 2020-04-29 20:12:36 +01:00
Gustavo Lopes
5eb1055447 Added unrar 5.7.3 2020-04-29 20:12:36 +01:00
Gustavo Lopes
7ca7561e09 Added unrar 5.7.2 2020-04-29 20:12:36 +01:00
Gustavo Lopes
61eca15136 Added unrar 5.7.1 2020-04-29 20:12:36 +01:00
Gustavo Lopes
dc8ee65999 Added unrar 5.6.8 2020-04-29 20:12:36 +01:00
Gustavo Lopes
656c3fa69d Added unrar 5.6.7 2020-04-29 20:12:36 +01:00
Gustavo Lopes
a6bea8fec8 Added unrar 5.6.6 2020-04-29 20:12:36 +01:00
Gustavo Lopes
3b405bea8e Added unrar 5.6.5 2020-04-29 20:12:36 +01:00
Gustavo Lopes
18cd0568aa Added unrar 5.6.4 2020-04-29 20:12:36 +01:00
Gustavo Lopes
dc298847c7 Added unrar 5.6.3 2020-04-29 20:12:36 +01:00
Gustavo Lopes
246a80fdeb Added unrar 5.6.2 2020-04-29 20:12:36 +01:00
Gustavo Lopes
4b6fd31d08 Added unrar 5.6.1 2020-04-29 20:12:36 +01:00
Gustavo Lopes
44e35b8f6a Added unrar 5.5.8 2020-04-29 20:12:36 +01:00
Gustavo Lopes
fe4a94305b Added unrar 5.5.7 2020-04-29 20:12:36 +01:00
Gustavo Lopes
0453380858 Suppress some warnings on unrar code 2020-04-29 19:40:03 +01:00
Gustavo Lopes
957fc7702d Merge pull request #4 from remicollet/issue-php73
Fix for PHP 7.3
2018-11-14 18:19:29 +00:00
Remi Collet
5a0cd32191 new constant names in 7.3 2018-08-16 14:52:03 +02:00
Remi Collet
5ca8d78562 fix for iterator changes in 7.3.0alpha4 2018-07-18 11:02:14 +02:00
Remi Collet
1225c9240e relax tests for 7.3 (bool/boolean, main/count) 2018-06-26 15:22:42 +02:00
Gustavo Lopes
10932c2450 Release 4.0.0 2017-07-22 04:00:29 +01:00
Gustavo Lopes
b79f595379 Add tests for RarEntry functions w/out one 2017-07-22 02:33:25 +01:00
Gustavo Lopes
479372f714 Fix redir functions; add test 2017-07-22 02:33:25 +01:00
Gustavo Lopes
121310f696 Refactor time functions to rar_time.c 2017-07-22 02:33:25 +01:00
Gustavo Lopes
43589ad851 Add badges 2017-07-21 18:48:04 +01:00
Gustavo Lopes
b3145c9883 Fix stat times not being in UTC
They depended on the system timezone, because the unrar lib returns them
in the local time.
2017-07-21 18:41:06 +01:00
Gustavo Lopes
5a9886a844 Windows support and appveyor 2017-07-21 18:41:06 +01:00
Gustavo Lopes
bdd4ce2357 Add redirection functions to RarEntry 2017-07-21 18:41:06 +01:00
Gustavo Lopes
2fd19b59ca Fix cloning of RarArchive being allowed 2017-07-21 18:41:06 +01:00
Gustavo Lopes
83756881c2 Rework to support 7.0 and 7.1 2017-07-21 18:40:58 +01:00
Gustavo Lopes
cc7edac87b Ignore unrar/.libs 2017-07-21 18:39:06 +01:00
Gustavo Lopes
a05875667e Travis: add one non-ZTS build 2017-07-18 03:57:34 +01:00
Gustavo Lopes
6bb74bf820 Fix swapped param order in extractchunk 2017-07-18 03:55:44 +01:00
Gustavo Lopes
1a2f9f5104 Fix tests/101.phpt 2017-07-18 03:55:44 +01:00
Gustavo Lopes
0fd6896a25 Remoe unneeded destructor 2017-07-18 03:55:44 +01:00
Gustavo Lopes
d2a8a89e64 Add travis files. 2017-07-18 03:55:44 +01:00
Gustavo Lopes
d95d7a794f Fix uninitialized struct passed to RARReadHeaderEx 2017-07-17 19:15:44 +01:00
Gustavo Lopes
9129dab024 Change compiler switches, remove unused variable 2017-07-17 17:31:41 +01:00
Gustavo Lopes
897139b2ce Remove & ignore autosave files 2017-07-17 17:23:21 +01:00
Gustavo Lopes
2a29f7e763 Remove now unneeded function 2017-07-17 17:22:52 +01:00
Gustavo Lopes
3a830bc07c Move to version 4 2017-07-17 17:10:11 +01:00
Gustavo Lopes
119722d581 Merge branch 'unrar', with unrar 5.5.6 2017-07-17 17:09:44 +01:00
Gustavo Lopes
4f821913ad Added unrar 5.5.6 2017-07-17 17:06:33 +01:00
Gustavo Lopes
6939711766 Added unrar 5.5.5 2017-07-17 17:06:33 +01:00
Gustavo Lopes
c499b4d2d2 Added unrar 5.5.4 2017-07-17 17:06:33 +01:00
Gustavo Lopes
a191673249 Added unrar 5.5.3 2017-07-17 17:06:33 +01:00
Gustavo Lopes
c6f8765250 Added unrar 5.5.2 2017-07-17 17:06:33 +01:00
Gustavo Lopes
5402805db0 Added unrar 5.5.1 2017-07-17 17:06:33 +01:00
Gustavo Lopes
e6e481cfb2 Added unrar 5.4.5 2017-07-17 17:06:33 +01:00
Gustavo Lopes
a3c0236a7d Added unrar 5.4.4 2017-07-17 17:06:33 +01:00
Gustavo Lopes
f8ee7cc273 Added unrar 5.4.3 2017-07-17 17:06:33 +01:00
Gustavo Lopes
e699b159cf Added unrar 5.4.2 2017-07-17 17:06:33 +01:00
Gustavo Lopes
41875e7bd6 Added unrar 5.4.1 2017-07-17 17:06:33 +01:00
Gustavo Lopes
3a2688b3eb Added unrar 5.3.11 2017-07-17 17:06:33 +01:00
Gustavo Lopes
524d195253 Added unrar 5.3.10 2017-07-17 17:06:33 +01:00
Gustavo Lopes
e1609b9dfd Added unrar 5.3.9 2017-07-17 17:06:33 +01:00
Gustavo Lopes
4f804014ca Added unrar 5.3.8 2017-07-17 17:06:33 +01:00
Gustavo Lopes
abe9816391 Added unrar 5.3.7 2017-07-17 17:06:33 +01:00
Gustavo Lopes
5876366b26 Added unrar 5.3.6 2017-07-17 17:06:33 +01:00
Gustavo Lopes
c1e389af0d Added unrar 5.3.5 2017-07-17 17:06:33 +01:00
Gustavo Lopes
73972e070d Added unrar 5.3.4 2017-07-17 17:06:33 +01:00
Gustavo Lopes
74aed951bb Added unrar 5.3.3 2017-07-17 17:06:33 +01:00
Gustavo Lopes
26929db6a9 Added unrar 5.3.2 2017-07-17 17:06:33 +01:00
Gustavo Lopes
4fb28f3858 Added unrar 5.3.1 2017-07-17 17:06:32 +01:00
Gustavo Lopes
4e04320979 Added unrar 5.2.7 2017-07-17 17:06:32 +01:00
Gustavo Lopes
b72aaff789 Added unrar 5.2.6 2017-07-17 17:06:32 +01:00
Gustavo Lopes
3b2d2eb296 Added unrar 5.2.5 2017-07-17 17:06:32 +01:00
Gustavo Lopes
166fe908ad Added unrar 5.2.4 2017-07-17 17:06:32 +01:00
Gustavo Lopes
0265686bbd Added unrar 5.2.3 2017-07-17 17:06:32 +01:00
Gustavo Lopes
f650a6e340 Added unrar 5.2.2 2017-07-17 17:06:07 +01:00
Gustavo Lopes
a20ca1559c Ensure RAR archive is always closed 2017-07-17 15:41:19 +01:00
Gustavo Lopes
2ab141deed Add test for RAR5 archive 2017-07-17 15:13:11 +01:00
Gustavo Lopes
498cad468e Merge pull request #1 from weltling/master
missing file in config.w32
2017-07-17 06:39:34 +01:00
Gustavo Lopes
65d5132550 Merge branch 'unrar'
Conflicts:
	unrar/UnRAR.vcproj
	unrar/UnRARDll.vcproj
	unrar/arccmt.cpp
	unrar/arcread.cpp
	unrar/cmddata.cpp
	unrar/dll.cpp
	unrar/dll.hpp
	unrar/dll.rc
	unrar/errhnd.hpp
	unrar/extract.cpp
	unrar/extract.hpp
	unrar/filefn.cpp
	unrar/headers.hpp
	unrar/makefile
	unrar/os.hpp
	unrar/rdwrfn.hpp
	unrar/unpack.cpp
	unrar/unpack.hpp
	unrar/unpack15.cpp
	unrar/version.hpp
	unrar/volume.cpp
2017-07-17 06:30:09 +01:00
Gustavo Lopes
358432a7eb Added unrar 5.2.1 2014-10-22 23:42:31 +02:00
Gustavo Lopes
bbeab2dc4e Added unrar 5.1.7 2014-10-22 23:42:12 +02:00
Gustavo Lopes
5f81d8688f Added unrar 5.1.6 2014-10-22 23:42:04 +02:00
Gustavo Lopes
d6dfd5054c Added unrar 5.1.5 2014-10-22 23:41:54 +02:00
Gustavo Lopes
5d1e369c38 Added unrar 5.1.4 2014-10-22 23:41:44 +02:00
Gustavo Lopes
2f36bd7cac Added unrar 5.1.3 2014-10-22 23:41:36 +02:00
Gustavo Lopes
34859cf5b4 Added unrar 5.1.2 2014-10-22 23:41:26 +02:00
Gustavo Lopes
99cb19e838 Added unrar 5.1.1 2014-10-22 23:41:16 +02:00
Gustavo Lopes
f19f569f44 Added unrar 5.0.14 2014-10-22 23:40:13 +02:00
Gustavo Lopes
762b1ae3b0 Added unrar 5.0.13 2014-10-22 23:40:04 +02:00
Gustavo Lopes
fe2d2f46e4 Added unrar 5.0.12 2014-10-22 23:39:57 +02:00
Gustavo Lopes
6391dc21ca Added unrar 5.0.11 2014-10-22 23:39:48 +02:00
Gustavo Lopes
98bcf3697a Added unrar 5.0.10 2014-10-22 23:39:02 +02:00
Gustavo Lopes
4cda46d212 Added unrar 5.0.8 2014-10-22 23:37:27 +02:00
Gustavo Lopes
b2bc8dc586 Added unrar 5.0.7 2014-10-22 23:37:18 +02:00
Gustavo Lopes
96eec2b31c Added unrar 5.0.6 2014-10-22 23:37:10 +02:00
Gustavo Lopes
d5f04a3a88 Added unrar 5.0.5 2014-10-22 23:36:59 +02:00
Gustavo Lopes
13cb064031 Added unrar 5.0.4 2014-10-22 23:36:47 +02:00
Gustavo Lopes
a238d20430 Added unrar 5.0.3 2014-10-22 23:36:30 +02:00
Gustavo Lopes
66e2666696 Added unrar 5.0.2 2014-10-22 23:36:01 +02:00
Gustavo Lopes
55a328ff22 Added unrar 5.0.1 2014-10-22 23:35:46 +02:00
Gustavo Lopes
e632e338ef Added unrar 5.0.0 2014-10-22 23:32:03 +02:00
Anatol Belski
2ea5d74e6d missing file in config.w32 2014-10-22 23:25:15 +02:00
Anatol Belski
5840034b59 Merge branch 'master' of https://github.com/cataphract/php-rar 2014-02-05 12:26:26 +01:00
Gustavo Lopes
d72ef1dbce Merge pull request #3 from tony2001/master
added PHP license to the package
2013-10-11 06:23:30 -07:00
Antony Dovgal
e2db202b89 reflect the fact that UnRar has its own license 2013-10-11 15:31:41 +04:00
Antony Dovgal
1cf4e2c02c add license to package.xml 2013-10-11 15:29:49 +04:00
Antony Dovgal
ee28abf175 add LICENSE fail 2013-10-11 15:29:34 +04:00
Gustavo Lopes
ece47716ab Merge pull request #2 from tony2001/master
v3.0.2 update
2013-10-11 01:53:56 -07:00
Antony Dovgal
388707153c version 3.0.2 is coming 2013-10-11 12:19:49 +04:00
Antony Dovgal
60cf649b85 allow rb mode for dirs, it won't hurt 2013-10-11 12:18:24 +04:00
Anatol Belski
113935cbc5 missing file in config.w32 2013-10-01 16:02:30 +02:00
Gustavo Lopes
881989bbac Allow 'rb' mode for opening rar entries 2013-04-28 21:13:34 +02:00
Gustavo Lopes
b1c3582301 Convert rar_navigation.c to unix line endings 2013-04-28 20:32:45 +02:00
Gustavo Lopes
1cfe9592c0 Remove trailing space 2013-04-28 20:32:45 +02:00
Antony Dovgal
c92f03f1e2 Use zend_read_property() to read object properties 2013-04-28 13:19:12 +02:00
Gustavo Lopes
430a8ba763 Merge branch 'unrar', with unrar 4.2.4.
Conflicts:
	unrar/dll.rc
	unrar/version.hpp
2012-12-16 18:11:42 +01:00
Gustavo Lopes
e2c046d88d Added unrar 4.2.4. 2012-12-16 17:39:34 +01:00
Gustavo Lopes
63d3b18405 Prepare for 3.0.1 release 2012-07-29 02:48:36 +00:00
Gustavo Lopes
6963ed8f43 Add .gitignore 2012-07-29 02:03:44 +00:00
Gustavo Lopes
0a57b9b313 Remove revision information 2012-07-29 02:02:35 +00:00
Gustavo Lopes
3b9dd4dd6e Added test for bug #59939 (can't reproduce) 2012-07-29 00:44:38 +00:00
Gustavo Lopes
28e2572026 Fix bad pointer in error message 2012-07-29 00:42:45 +00:00
Gustavo Lopes
21cba90843 Fix some tests for when TZ != 'Europe/Lisbon' 2012-07-29 00:28:32 +00:00
Gustavo Lopes
0473c464e1 Fix problem in PHP >= 5.3.11, 5.4.1
And not compiling in master.
2012-07-29 02:15:57 +02:00
Gustavo Lopes
9cd367de03 Use <> in standard includes 2012-07-28 23:13:30 +00:00
Gustavo Lopes
0ef63a5fbb Merge branch 'unrar', with unrar 4.2.2
Conflicts:
	unrar/UnRAR.vcproj
	unrar/UnRARDll.vcproj
	unrar/arcread.cpp
	unrar/cmddata.cpp
	unrar/dll.cpp
	unrar/dll.rc
	unrar/errhnd.hpp
	unrar/extract.cpp
	unrar/makefile.bcc
	unrar/makefile.dj
	unrar/makefile.dmc
	unrar/makefile.unix
	unrar/os.hpp
	unrar/unpack.hpp
	unrar/version.hpp
	unrar/volume.cpp
2012-07-29 00:53:30 +02:00
Gustavo Lopes
75486ffa92 Merge with strategy ours 1e542a4db.
This will allow to merge in new changes int he unrar lib without using
a temporary branch.
2012-07-28 16:26:51 +02:00
Gustavo Lopes
7d8ada6e1e Added unrar 4.2.2. 2012-07-28 01:40:45 +02:00
Gustavo Lopes
02e98e3188 Added unrar 4.2.2. 2012-07-28 01:40:10 +02:00
Gustavo Lopes
18a025c38d Added unrar 4.2.1. 2012-07-28 01:06:28 +02:00
Gustavo Lopes
3bd27b4b36 Added unrar 4.1.4. 2012-07-28 00:58:41 +02:00
Gustavo Lopes
5bb815b5db Added unrar 4.1.3. 2012-07-28 00:58:06 +02:00
Gustavo Lopes
e06c6250d0 Merged in changes in unrar 4.1.1 and 4.1.2. 2011-11-02 11:48:33 +00:00
Gustavo Lopes
1e542a4db3 Added unrar 4.1.2 2011-11-02 11:14:35 +00:00
Gustavo Lopes
6907905144 Added unrar 4.1.1 2011-11-02 11:14:22 +00:00
cataphract
eca703e481 Preparing for 3.0.0 release
git-svn-id: https://svn.php.net/repository/pecl/rar/trunk@312082 c90b9560-bf6c-de11-be94-00142212c4b1
2011-06-12 04:59:29 +01:00
cataphract
47ff0254ea Fixed tests.
git-svn-id: https://svn.php.net/repository/pecl/rar/trunk@312078 c90b9560-bf6c-de11-be94-00142212c4b1
2011-06-12 03:24:53 +01:00
cataphract
1f4496b5b0 Added unrar 4.0.7
git-svn-id: https://svn.php.net/repository/pecl/rar/trunk@312077 c90b9560-bf6c-de11-be94-00142212c4b1
2011-06-12 03:24:53 +01:00
Gustavo Lopes
f8cb60259d Added unrar 4.0.7 2011-06-12 02:09:21 +01:00
Gustavo Lopes
1e2e912de2 Added unrar 4.0.6. 2011-02-17 19:07:06 +00:00
cataphract
3c74636516 Merge branch 'unrar_temp', with changes in unrar 4.0.5.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@307694 c90b9560-bf6c-de11-be94-00142212c4b1
2011-01-24 04:43:38 +00:00
cataphract
02c0f562a8 Added README to package.xml file list.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@307693 c90b9560-bf6c-de11-be94-00142212c4b1
2011-01-24 04:43:20 +00:00
Gustavo Lopes
36c26dacda Merge with unrar 4.0.5. 2011-01-24 04:38:23 +00:00
Gustavo Lopes
479c373f4d Added unrar 4.0.5 2011-01-24 04:22:35 +00:00
cataphract
c9373a4869 Added README file.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@307471 c90b9560-bf6c-de11-be94-00142212c4b1
2011-01-14 11:40:42 +00:00
cataphract
d35e6962c4 Fixed year in unrar/version.hpp
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@307458 c90b9560-bf6c-de11-be94-00142212c4b1
2011-01-13 23:53:03 +00:00
cataphract
9cdbc652ed Merge branch 'unrar_temp', with changes in unrar 4.0.3 and 4.0.4.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@307448 c90b9560-bf6c-de11-be94-00142212c4b1
2011-01-13 20:12:45 +00:00
Gustavo Lopes
14afaf33a9 Updated to unrar 4.0.4 2011-01-13 20:08:31 +00:00
Gustavo Lopes
25087577be Updated to version 4.0.3 2011-01-13 19:36:45 +00:00
Gustavo Lopes
6c1dd8a81f Added unrar 4.0.4 2011-01-13 18:50:03 +00:00
Gustavo Lopes
b451c7c79b Added unrar 4.0.3 2011-01-13 18:49:58 +00:00
Gustavo Lopes
c915d361f4 Added unrar 4.0.2 2011-01-13 18:49:54 +00:00
Gustavo Lopes
15aa6f20d6 Added unrar 4.0.1 2011-01-13 18:49:44 +00:00
Gustavo Lopes
561966f23b Added unrar 3.9.10 2011-01-13 18:49:25 +00:00
Gustavo Lopes
80986445f5 Added unrar 3.9.9 2011-01-13 18:49:13 +00:00
Gustavo Lopes
446a2e8492 Added unrar 3.9.8 2011-01-13 18:49:00 +00:00
Gustavo Lopes
12719dce2c Added unrar 3.9.7 2011-01-13 18:48:55 +00:00
Gustavo Lopes
75c4bbc240 Added unrar 3.9.6 2011-01-13 18:48:50 +00:00
Gustavo Lopes
951ccf9767 Added unrar 3.9.5 2011-01-13 18:48:45 +00:00
Gustavo Lopes
2538d242ee Added unrar 3.9.4 2011-01-13 18:48:41 +00:00
Gustavo Lopes
e91808a5eb Added unrar 3.9.3 2011-01-13 18:48:36 +00:00
Gustavo Lopes
a9631cfddd Added unrar 3.9.2 2011-01-13 18:48:32 +00:00
Gustavo Lopes
89c4cbe487 Added unrar 3.9.1 2011-01-13 18:48:26 +00:00
Gustavo Lopes
876cb51c4c Added unrar 3.8.5 2011-01-13 18:47:51 +00:00
Gustavo Lopes
ad8e1e2a2b Added unrar 3.8.4 2011-01-13 18:47:45 +00:00
Gustavo Lopes
825de01ac1 Added unrar 3.8.3 2011-01-13 18:47:39 +00:00
Gustavo Lopes
7a8b0a7f59 Added unrar 3.8.2 2011-01-13 18:47:31 +00:00
Gustavo Lopes
35f7e43f2f Added unrar 3.8.1 2011-01-13 18:47:24 +00:00
Gustavo Lopes
3a535eba4e Added unrar 3.7.8 2011-01-13 18:47:06 +00:00
Gustavo Lopes
a16b24d665 Added unrar 3.7.7 2011-01-13 18:47:00 +00:00
Gustavo Lopes
9bd14a69e8 Added unrar 3.7.6 2011-01-13 18:46:54 +00:00
Gustavo Lopes
c093245020 Added unrar 3.7.5 2011-01-13 18:46:49 +00:00
Gustavo Lopes
f5ca2159f0 Added unrar 3.7.4 2011-01-13 18:46:44 +00:00
Gustavo Lopes
b8102334c6 Added unrar 3.7.3 2011-01-13 18:46:33 +00:00
Gustavo Lopes
eaffae90c0 Added unrar 3.7.2 2011-01-13 18:46:27 +00:00
Gustavo Lopes
2e18f53535 Added unrar 3.7.1 2011-01-13 18:46:22 +00:00
Gustavo Lopes
fff0c56e2e Added unrar 3.6.8 2011-01-13 18:46:12 +00:00
Gustavo Lopes
59a53d18ed Added unrar 3.6.7 2011-01-13 18:46:05 +00:00
Gustavo Lopes
e1490118df Added unrar 3.6.6 2011-01-13 18:46:00 +00:00
Gustavo Lopes
7bacdf6736 Added unrar 3.6.5 2011-01-13 18:45:55 +00:00
Gustavo Lopes
00a58e1934 Added unrar 3.6.4 2011-01-13 18:45:40 +00:00
Gustavo Lopes
55dd7388ab Added unrar 3.6.3 2011-01-13 18:44:53 +00:00
Gustavo Lopes
a18c3b7fdc Added unrar 3.6.2 2011-01-13 18:44:41 +00:00
Gustavo Lopes
c3cf0e0dd4 Added unrar 3.6.1 2011-01-13 18:44:23 +00:00
cataphract
bf0df5d1ed Restored PHP 5.2 compatibility.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@307252 c90b9560-bf6c-de11-be94-00142212c4b1
2011-01-08 04:47:02 +00:00
cataphract
010ca980e0 Fixed non-ZTS build on compilers that don't support C99-style non-top declarations.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@307250 c90b9560-bf6c-de11-be94-00142212c4b1
2011-01-08 03:49:03 +00:00
cataphract
b92bcc5d5f - Fixed a build failure on gcc.
- Changed // comments into /* ones on C portions.
- Simplified the output of some stat tests.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@306221 c90b9560-bf6c-de11-be94-00142212c4b1
2010-12-11 05:56:20 +00:00
cataphract
da39115344 - Merge with RAR 4.0.2
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@306117 c90b9560-bf6c-de11-be94-00142212c4b1
2010-12-09 07:54:59 +00:00
cataphract
5947ee8db4 - Fixed PECL bug #18449 (Extraction of uncompressed and encrypted files fails).
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@306110 c90b9560-bf6c-de11-be94-00142212c4b1
2010-12-09 05:13:01 +00:00
cataphract
3fbc9ce3e9 - Removed repeated declaration of _rar_strnlen in rar.c in case HAVE_STRNLEN is set to 0/doesn't exist.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@302821 c90b9560-bf6c-de11-be94-00142212c4b1
2010-08-26 17:07:38 +00:00
cataphract
45dbaf4a4f - Bumped version to 3.0.0.
- Fixed arginfo for RarArchive::setAllowBroken.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@300956 c90b9560-bf6c-de11-be94-00142212c4b1
2010-07-02 23:08:20 +00:00
cataphract
681739fbb5 Fixed arginfo for RarEntry::extract.
Safer string copy functions in extractchunk.cpp.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@300932 c90b9560-bf6c-de11-be94-00142212c4b1
2010-07-02 04:55:28 +00:00
cataphract
d7d2318aad - An "extern" keyword was missing in php_rar.h.
#see http://stackoverflow.com/questions/1490693

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@300431 c90b9560-bf6c-de11-be94-00142212c4b1
2010-06-14 13:50:54 +00:00
cataphract
9cd2943b79 - I give up.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@300146 c90b9560-bf6c-de11-be94-00142212c4b1
2010-06-03 04:47:07 +00:00
cataphract
d9ccfe265f - Fixed actual revision of test file being in the test file (or
something).


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@300145 c90b9560-bf6c-de11-be94-00142212c4b1
2010-06-03 04:46:04 +00:00
cataphract
8aba0685be - Test #96 cannot have Revision SVN keyword.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@300144 c90b9560-bf6c-de11-be94-00142212c4b1
2010-06-03 04:38:56 +00:00
cataphract
a6b4c57b1c - Added module info test.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@300143 c90b9560-bf6c-de11-be94-00142212c4b1
2010-06-03 04:34:00 +00:00
cataphract
535f0ea828 - Added test for wrapper cache eviction (required adding the function rar_wraper_cache_stats).
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@300141 c90b9560-bf6c-de11-be94-00142212c4b1
2010-06-03 04:17:48 +00:00
cataphract
5d1aafd746 - Oops forgot to commit the tests
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@300084 c90b9560-bf6c-de11-be94-00142212c4b1
2010-06-02 03:51:46 +00:00
cataphract
9d49ce4842 - Omitted volume not found warning if volume callback was specified.
. rar_broken_is omits no warnings (except the volume not found one, but see above)
- Tests for reading broken files
- Other tests for rararch.c

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@300083 c90b9560-bf6c-de11-be94-00142212c4b1
2010-06-02 03:20:10 +00:00
tony2001
438d8a4b0b fix compile warnings
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@300028 c90b9560-bf6c-de11-be94-00142212c4b1
2010-06-01 08:32:41 +00:00
cataphract
1e97aa1ef1 - Added unset_dimension handler.
- Added remaining tests for the dimension handlers.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@300016 c90b9560-bf6c-de11-be94-00142212c4b1
2010-06-01 01:15:07 +00:00
cataphract
929b252665 - Fixed bug in dimensions handler.
- Added tests for read_dimensions handler.
- Methods/functions that receive no parameters enforce that.
- Added rar_is_broken and rar_allow_broken_set.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@300009 c90b9560-bf6c-de11-be94-00142212c4b1
2010-05-31 20:05:42 +00:00
cataphract
7bfe225895 - Implemented dimensions handlers.
- foreach no longer works for incomplete archives (will be possible again in the future via a new method in RarArchive).
- On incomplete archives, rar_list and rar_entry_get always fail instead of failing the first time and being successful subsequently.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@299970 c90b9560-bf6c-de11-be94-00142212c4b1
2010-05-31 04:10:39 +00:00
cataphract
dff57d32cb - Implemented count elements handler for RarArchive.
- Fixed handling of archives with no entries.
- Removed trailing full stops from some error messages.
- Substituted zend_error for php_error_docref.
- Fixed inconsistent behavior of EOF for streams (reading at file boundaries would could set EOF or not).

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@299945 c90b9560-bf6c-de11-be94-00142212c4b1
2010-05-30 00:51:55 +00:00
tony2001
71fb41635c fix build
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@299933 c90b9560-bf6c-de11-be94-00142212c4b1
2010-05-29 11:23:18 +00:00
cataphract
9a7227a9e0 - Storage of the entries and its navigation were reformulated. The previous array with raw entries was substituted with an array with unique entries that also stores the directory depth and length of the entry name. The hash table used for direct access (url stater mainly) was substituted for a sorted array that makes directory navigation more efficient. The penalty of losing constant time access to entries by name (now it takes log n) was mitigated by a cache that is optimized for stating every element while a directory or the whole file are being traversed.
- RAR navigation and indexing were moved to rar_navigation.c.
- RAR archives that contain entries with the same name are correctly handled.
- Changed the way properties are accessed in RarEntry (does not require building the properties table in trunk).
- Fixed memory leak in silent url stat.
- Fixed handling of optional passwords. Now giving no password, NULL or '' result in the same behavior.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@299926 c90b9560-bf6c-de11-be94-00142212c4b1
2010-05-29 02:28:23 +00:00
tony2001
79b78f81b9 fix build on Linux
add support for PHP's trunk
fix segfault in rar streams


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@299793 c90b9560-bf6c-de11-be94-00142212c4b1
2010-05-26 15:10:43 +00:00
cataphract
b1a21bb20c _S_IFDIR -> S_IFDIR
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@299747 c90b9560-bf6c-de11-be94-00142212c4b1
2010-05-25 17:12:29 +00:00
cataphract
a72bceba89 Minor improvements, let's hope it compiles on linux.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@299746 c90b9560-bf6c-de11-be94-00142212c4b1
2010-05-25 17:06:19 +00:00
cataphract
d2e33c32c0 Fixed a few bugs, memory leaks and removed some old compatibility code.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@299743 c90b9560-bf6c-de11-be94-00142212c4b1
2010-05-25 16:00:45 +00:00
cataphract
b081085cc9 Added option to RarEntry::extract() to allow from extraction of ACL (windows)/owner (unix)/extended attributes (os/2)
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@299044 c90b9560-bf6c-de11-be94-00142212c4b1
2010-05-05 23:43:28 +00:00
cataphract
ffde50b702 Fixed RarEntry::extract not really accepting a password.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@299004 c90b9560-bf6c-de11-be94-00142212c4b1
2010-05-05 01:06:21 +00:00
cataphract
8bab79ae80 Exposed access time and creation time for stat/fstat.
Used the high precision modification time to create the time_t for stat/fstat, if it exists.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@298999 c90b9560-bf6c-de11-be94-00142212c4b1
2010-05-05 00:04:16 +00:00
cataphract
dadab995f5 Directory streams and url stat implemented.
Exposed UnRAR DLL API version in MINFO.
Refactoring and a few other minor changes.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@298980 c90b9560-bf6c-de11-be94-00142212c4b1
2010-05-04 17:17:01 +00:00
cataphract
0f950603be Refactoring.
Fixed tests 49 and 56.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@298807 c90b9560-bf6c-de11-be94-00142212c4b1
2010-04-30 14:48:07 +00:00
cataphract
a88a995ca0 Added extflow.txt.
Added technote.txt.
Added rar_file_t::entries_idx. It's a hashtable that stores the entries in rar_file_t::entries indexed by name. _rar_raw_entries_to_files uses it, if available.
Added an extension global, a per-request cache that will be used when directory streams are implemented.
Eliminated dependency on SPL.
Substituted several legacy macro names for new ones.
Stream close operation operates differently when close_handle is FALSE (not that I actually know what the correct behaviour would be...)
Added rar stream stat operation.
Added wrapper, not with only an opener. The syntax is "rar://<urlencoded path to RAR archive>#<urlencoded entry name>". Context options should be under "rar" and are "open_password", "file_password" and "volume_callback"
extract() and the wrapper opener should support RAR files with header passwords different from file passwords (but WinRAR does not generate them, so not tested).
Avoid test 46 infinite loop on resource opening failure.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@298704 c90b9560-bf6c-de11-be94-00142212c4b1
2010-04-28 15:42:06 +00:00
cataphract
f92f731da3 Change in the unRAR library: omit strcpy calls in File::Open when src and dst are the same.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@298405 c90b9560-bf6c-de11-be94-00142212c4b1
2010-04-24 01:17:16 +00:00
cataphract
99996abdb9 Fixed test 49.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@298403 c90b9560-bf6c-de11-be94-00142212c4b1
2010-04-23 22:57:50 +00:00
cataphract
eb12649fb2 Tests for when MAXPATHLEN > 1024 and improved resilience to possible unterminated strings in the unRAR lib (shouldn't happen anyway).
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@298400 c90b9560-bf6c-de11-be94-00142212c4b1
2010-04-23 22:42:24 +00:00
cataphract
506493c52d Added volume find callback to RarArchive::open/rar_open.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@298372 c90b9560-bf6c-de11-be94-00142212c4b1
2010-04-23 11:01:14 +00:00
cataphract
3c8d037135 Added test for files when unpacked size bigger than 2 GiB (it will take some effort to do the same for packed size > 2 GiB).
Relaxed test #12 (changes to the unpacking algorithm in unrar 3.9.10 have apparently changed the output stream for corrupted entries).

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@298254 c90b9560-bf6c-de11-be94-00142212c4b1
2010-04-21 14:13:43 +00:00
cataphract
2fb18b2fe4 Fixed packed sizes using high bits from unpacked sizes.
Changed the check on the size of longs so that the compiler does not complain when long is 32-bit long.
Added unrar.dll documentation.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@298248 c90b9560-bf6c-de11-be94-00142212c4b1
2010-04-21 11:46:04 +00:00
cataphract
8f206263cb Merged with UnRAR 3.9.10 (RAR 3.9.3).
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@298232 c90b9560-bf6c-de11-be94-00142212c4b1
2010-04-20 19:22:30 +00:00
cataphract
0f76b938a4 Preparing for 2.0.0 release.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@298212 c90b9560-bf6c-de11-be94-00142212c4b1
2010-04-20 12:26:15 +00:00
cataphract
670290aad1 Renamed RarArchive::list() to RarArchive::getEntries() (see bug #17025). The old name of the method can be activated by defining RAR_ARCHIVE_LIST_ALIAS.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@298209 c90b9560-bf6c-de11-be94-00142212c4b1
2010-04-20 11:32:30 +00:00
johannes
82d3711a99 s,function_entry,zend_function_entry,
As announced in http://news.php.net/php.pecl.dev/7123


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@297236 c90b9560-bf6c-de11-be94-00142212c4b1
2010-03-31 20:39:48 +00:00
cataphract
af49aafb1d Listed files added in the previous commit to package.xml.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@295911 c90b9560-bf6c-de11-be94-00142212c4b1
2010-03-07 00:50:00 +00:00
cataphract
7288320a37 Fixed infinite loop when opening files with missing volumes.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@295909 c90b9560-bf6c-de11-be94-00142212c4b1
2010-03-07 00:43:31 +00:00
cataphract
fc23699737 Fixed config.w32 for static configurations.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@293697 c90b9560-bf6c-de11-be94-00142212c4b1
2010-01-18 11:04:24 +00:00
cataphract
fffcb9d508 Updated bundled UnRAR lib to 3.9.7. Deleted two redundant files.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@293691 c90b9560-bf6c-de11-be94-00142212c4b1
2010-01-18 04:09:51 +00:00
cataphract
79afa19815 Fixed RarException::isUsingExceptions parsing a boolean argument into a long, which made the value depend on uninitialized data.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@293642 c90b9560-bf6c-de11-be94-00142212c4b1
2010-01-17 09:53:07 +00:00
cataphract
02855820f7 Fixed test 32 (trivial).
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@293638 c90b9560-bf6c-de11-be94-00142212c4b1
2010-01-17 08:54:43 +00:00
cataphract
5f7b823e40 Fixed two bugs:
RarArchive get iterator on closed file caused crash.
rararch_it_current_data was copying the address of a stack allocated variable. Only caught this when testing on release PHP 5.2 under Linux.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@293637 c90b9560-bf6c-de11-be94-00142212c4b1
2010-01-17 08:46:30 +00:00
cataphract
59437d527f package.xml: Release Candidate versions must have upper-case RC, not
lower-case rc


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@293626 c90b9560-bf6c-de11-be94-00142212c4b1
2010-01-16 20:55:07 +00:00
cataphract
9be4e1e0e3 package.xml updated.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@293625 c90b9560-bf6c-de11-be94-00142212c4b1
2010-01-16 20:52:17 +00:00
cataphract
7089587b9e Fixed memory leaks.
Tab -> space in package.xml

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@292721 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-28 17:41:29 +00:00
cataphract
43dc0541aa Fixed missing definitions in 5.2.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@292701 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-27 19:34:35 +00:00
cataphract
36b2b5d2fc Hopefully fixed non-ZTS compilation.
Fixed test #34.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@292692 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-27 15:58:53 +00:00
cataphract
4e2dc20b2d Renamed rar_solid_get to rar_solid_is.
RarException::setUsingExceptions no longer returns anything.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@292614 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-24 20:28:10 +00:00
cataphract
61183fa339 Fixed prototypes and header missing.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@292612 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-24 18:53:36 +00:00
cataphract
7da530c6e3 Added error handling with exceptions.
Introduction of RarException.
Added rar_solid_get
RarEntry and RarArchive cannot be instantiated in user space.
Quite some refactoring.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@292412 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-21 14:04:56 +00:00
cataphract
b7794e851d Fixed line endings, added svn properties on rararch.c
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@292391 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-21 00:40:56 +00:00
cataphract
444ee4b790 RarArchive made traversable.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@292194 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-16 10:49:54 +00:00
tony2001
51b5b9b267 state the truth
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291943 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-10 10:38:46 +00:00
cataphract
65758585af Restored LPARAM to long and let's hope sizeof(long) == sizeof(void*) in non-windows platforms.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291824 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-07 16:48:43 +00:00
cataphract
5966259561 Reverted accidental package.xml change.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291823 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-07 16:17:17 +00:00
cataphract
67d29529f1 Fix for Linux compilation.
Tests correction and relaxation where required.


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291822 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-07 16:08:33 +00:00
cataphract
e09548cd2f Hopefully fixed VC6 compilation, added two more tests and updated package.xml
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291820 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-07 15:34:13 +00:00
cataphract
6faef72502 Fixed RarArchive::getEntry not working.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291805 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-07 07:42:17 +00:00
cataphract
c39465fa08 Fixed an obvious mistake.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291802 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-07 06:36:53 +00:00
cataphract
633a15f4b4 Refactoring/added RarArchive class.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291800 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-07 06:12:39 +00:00
cataphract
c4432e6c4b Hopefully fixed non-windows building.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291730 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-05 01:16:36 +00:00
cataphract
81934056d0 Proper support for encrypted files.
Restored C-like feof semantics.
Added tests with encrypted files and unix directories and links.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291532 c90b9560-bf6c-de11-be94-00142212c4b1
2009-12-01 00:38:02 +00:00
cataphract
896a5d3a91 Same as last commit, but this time with the correct changes...
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291452 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 19:21:06 +00:00
cataphract
a153f2ba84 Correct fixes for tests in PHP 5.2.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291451 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 19:05:05 +00:00
cataphract
6c8276f3c8 Fixed PHP 5.2 branch compatibility.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291450 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 19:00:18 +00:00
cataphract
380eb4fd06 Fixed typo.
Fixed package.xml.
Promoted to beta.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291447 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 17:59:29 +00:00
cataphract
c502332f09 Updated package.xml and CREDITS. Release 2.0.0snap29112009
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291442 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 17:34:07 +00:00
cataphract
e64419b1c3 Fixed two memory leaks reported by the zend engine.
Fixed expected output of test 021 to work in linux.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291440 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 16:17:48 +00:00
cataphract
a9d71e2adb Added missing prototype in rarentry.c. Currently a no-op since the usage of the function was below its definition.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291421 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 13:24:57 +00:00
cataphract
c56f0c4ad9 rarentry.c: added header, added svn properties and wrapped in an extern C in case of compilation with a C++ compiler.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291420 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 13:19:02 +00:00
cataphract
6de793130a Refactoring.
Added a bunch of constants to RarEntry.
Fixed possible crash with empty RAR files (though WinRAR doesn't let you create empty RAR files)
Added __toString method
All RarEntry properties are now private.
Made most methods not implementation dependent.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291411 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-29 03:41:11 +00:00
cataphract
ba66f77e5f Test for RarEntry::getStream() with diectories.
feof marked right after creation of stream if it can right then be determined that there are no bytes to be read. These are not C feof semantics, but I can find no documentation that says this is forbidden.
_rar_list_files now doesn't call realloc every time it processes a header (allocates powers of 2), thus improving performance.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291326 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-26 01:40:14 +00:00
cataphract
f93c189947 Added RarEntry::isDirectory().
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291303 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-25 11:22:03 +00:00
cataphract
5ba817d02c Test #012 had to be further relaxed.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291222 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-23 19:27:23 +00:00
cataphract
3655bf9e21 Fixed test #016 (file count correct). It's irrelevant that the file
count is correct because you won't be able to extract the files that 
ended up with the same wide file name, but now the test passes...
Test #012 still wouldn't pass, so it was relaxed.


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291221 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-23 19:26:03 +00:00
cataphract
3254b497a2 Fixed bug in unrarlib that makes tests 012 and 016 fail less miserably.
On dll.cpp on line 193, CharToWide is called but the return value is 
not checked. CharToWide calls mbstowcs(), which stops when an invalid 
multibyte sequence is encountered and returns -1. So the string will be 
truncated until before the invalid sequence and Dest buffer will not be 
L'\0'-terminated unless you happened to fill RARHeaderDataEx with 0's 
before (for instance, if you called calloc to allocate the memory).
Fixed by checking the return value and force try to do the conversion 
via UtfToWide, which handles the conversion more gracefully (ignores 
invalid sequences).


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291220 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-23 18:42:59 +00:00
cataphract
da1c055202 Hopefully fixed tests #012 and #016 in platforms with 32-bit wchar_t.
Arc->FilenameW could have invalid unicode characters that were discarded when converted into multi-byte UTF-8 string.
Then _rar_find_file would convert UTF-8 back to multi-character and compare with Arc->FilenameW, thus failing. Now Arc->FilenameW is fixed before the comparison by removing its invalid characters.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291199 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-23 13:01:20 +00:00
cataphract
d3ffa6d3ba Small corrections.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291166 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-23 00:49:10 +00:00
cataphract
8d24ef1195 Added tests for solid archives and archives with the store method.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291147 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-22 19:48:03 +00:00
cataphract
84d8d1c93f Fixed volumes opened with middle volumes showing files continued from previous volume with incorrect packed and unpacked sizes. Though that is the behavior of WinRAR, I prefer not to show files continued from previous volume altogether.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291145 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-22 18:57:37 +00:00
cataphract
22be3d8ee9 Fixed integer division by 0 in a different way from last commit. This method also saves unnecessary calls to RARProcessFileChunk.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291142 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-22 16:07:39 +00:00
cataphract
397d6de791 Refactoring.
Interim fix for crash in test 12. It would be nice to know what's going on.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291126 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-22 03:14:09 +00:00
cataphract
6d00347ddd Fixed PECL bug #9649 - resource is now destroyed regardless of the le->refcount
Fixed consistency between RarEntry::getName and RarEntry::getStream, which exposed integer division by zero.
Teste #012 now fails.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291119 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-21 18:56:40 +00:00
cataphract
1401a0604c Had removed arginfo inadvertedly. That accident was fixed.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291116 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-21 15:17:17 +00:00
cataphract
d033b8f836 PHP 5.2 compatibility and linux compilability.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291113 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-21 12:09:39 +00:00
cataphract
b15940e101 Fixed svn:keywords for rar_stream.cpp
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291093 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-20 15:52:33 +00:00
cataphract
829e402dbb Fixed phpinfo version information.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291092 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-20 15:48:40 +00:00
cataphract
48c55f71ea Added test to ::getStream() with corrupted file.
Fixed incoherence between ::getName() and rar_entry_get and added test for that.
Restructured ::extract(), now with relative paths fixed for the second argument.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291089 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-20 14:58:48 +00:00
felipe
9876090ea6 - Added arginfo
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291071 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-20 11:56:32 +00:00
cataphract
3a71ec0c0f Fixed the config files.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291047 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-19 23:40:02 +00:00
cataphract
c52d6a92a6 Stream support added. Still missing tests with corrupted files.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291023 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-19 18:45:31 +00:00
cataphract
8f65391767 Handles unicode filenames (uses UTF-8 external encoding).
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291015 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-19 17:32:04 +00:00
cataphract
3f841aca84 Test 004.phpt relied on undocumented behavior that had been broken in the last commit. Old behavior emulated, test now passes without modifications.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291012 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-19 16:35:45 +00:00
cataphract
d39e216566 Fixed the relative path bug for RarEntry::extract()
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@291009 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-19 16:18:21 +00:00
cataphract
ed74b331d8 Fixed by pecl bug #8821 by using expand_filepath.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290966 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-19 05:42:39 +00:00
cataphract
36e67a3493 Fixed warning message not being shown when rar_entry_get was called with a file that did not exist.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290965 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-19 04:23:22 +00:00
cataphract
d6673b97fd Fixed pecl bug #9470 by changing the list method (now there can be multiple entries per file).
Added rar_comment_get.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290964 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-19 04:02:37 +00:00
cataphract
04ac7f6eba changed type from HANDLE back to void * (change had broken non-windows compilation).
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290945 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-18 21:22:00 +00:00
cataphract
a4b1479338 Fixed compilation.
Updated code to use extended unrar lib structures.
rar_open gives more detailed error messages on failure. Updated tests accordingly.
Changed version from 2.0-dev to 2.0.0-dev, as I understand that's the convention.

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290943 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-18 21:12:27 +00:00
cataphract
d528906ec7 Made some modifications to the unrar lib in order to allow partial and resumable extraction. It is not complete (probably crashes on corrupted files, for instance), but it should NOT break the functionality currently implemented in the Rar extension.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290924 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-18 17:46:10 +00:00
cataphract
3c08bc522f Previous commit had inadvertedly eaten away two slashes. Fixed.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290916 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-18 14:56:13 +00:00
cataphract
dc4037e8ed Fixed build in linux by adding two headers that handle os-dependent
stuff.
Added -Wno-write-strings to suppress warning about deprecated conversion from string constant to ‘char*’.


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290915 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-18 14:23:48 +00:00
cataphract
b79060c741 Updated bundled unrar lib to version 3.90 or 3.9.6 depending on whether the download file name of version.hpp is correct...
Changed version number to 2.0-dev

git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290883 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-17 19:26:03 +00:00
cataphract
2ea98f9c07 php_rar now compiles on Windows.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@290872 c90b9560-bf6c-de11-be94-00142212c4b1
2009-11-17 16:12:40 +00:00
gwynne
40b585bc2f fix a huge number of wrong MIME types. UGH.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@284003 c90b9560-bf6c-de11-be94-00142212c4b1
2009-07-13 12:15:13 +00:00
tony2001
62ebac8d88 update my email
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@264972 c90b9560-bf6c-de11-be94-00142212c4b1
2008-08-16 10:16:46 +00:00
sfox
cf7947cbbd - Bring the majority of PECL extensions into line with macro/x.x.x versioning.
- Please use the -dev tag during the development cycle so that snapshots can easily be distinguished from releases.


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@256498 c90b9560-bf6c-de11-be94-00142212c4b1
2008-03-31 10:10:01 +00:00
tony2001
f6900cb024 update package.xml
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@253819 c90b9560-bf6c-de11-be94-00142212c4b1
2008-02-26 13:29:00 +00:00
tony2001
fa8c1c8aa8 updated UnRar to version 3.7.8
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@253818 c90b9560-bf6c-de11-be94-00142212c4b1
2008-02-26 13:27:57 +00:00
tony2001
4d7c5fc2c4 add UnRAR version to phpinfo() output
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@253817 c90b9560-bf6c-de11-be94-00142212c4b1
2008-02-26 13:27:25 +00:00
tony2001
10d2444b31 fix protos (thanks to Philip)
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@247309 c90b9560-bf6c-de11-be94-00142212c4b1
2007-11-29 21:12:55 +00:00
tony2001
63e0df6078 ifdef safe_mode and fix build with HEAD
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@241940 c90b9560-bf6c-de11-be94-00142212c4b1
2007-08-30 10:35:10 +00:00
tony2001
54ac112b0d use PHPs flock() on AIX
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@241421 c90b9560-bf6c-de11-be94-00142212c4b1
2007-08-17 10:08:54 +00:00
tony2001
9ec063426c no point to keep it forever..
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@241275 c90b9560-bf6c-de11-be94-00142212c4b1
2007-08-15 18:26:30 +00:00
tony2001
1d4ad5767b prepare to 1.0.0
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@241273 c90b9560-bf6c-de11-be94-00142212c4b1
2007-08-15 17:12:54 +00:00
tony2001
0866f20178 nuke unused variable
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@241211 c90b9560-bf6c-de11-be94-00142212c4b1
2007-08-14 09:14:22 +00:00
tony2001
5db1495374 convert to 2.0, update & prepare to 1.0.0 release
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@241187 c90b9560-bf6c-de11-be94-00142212c4b1
2007-08-13 21:48:26 +00:00
tony2001
75f63eae35 updated unRar to version 3.7.6
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@241183 c90b9560-bf6c-de11-be94-00142212c4b1
2007-08-13 21:39:53 +00:00
tony2001
5f0d4b1516 fix bug #11430 (rar_extract() doesn't close handles gracefully)
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@238531 c90b9560-bf6c-de11-be94-00142212c4b1
2007-06-25 11:59:11 +00:00
tony2001
7430bfae21 update package.xml
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@229866 c90b9560-bf6c-de11-be94-00142212c4b1
2007-02-15 15:07:14 +00:00
tony2001
3010bc351e upgrade to 3.7.3
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@229865 c90b9560-bf6c-de11-be94-00142212c4b1
2007-02-15 15:05:54 +00:00
tony2001
bfaaaa95fe update package.xml
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@221632 c90b9560-bf6c-de11-be94-00142212c4b1
2006-10-12 16:09:56 +00:00
tony2001
379f5d1d43 fix PECL bug #9002
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@221631 c90b9560-bf6c-de11-be94-00142212c4b1
2006-10-12 16:07:47 +00:00
tony2001
f45fb54b0a path is always not NULL
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@220163 c90b9560-bf6c-de11-be94-00142212c4b1
2006-09-18 10:48:48 +00:00
tony2001
e4d1885168 update package.xml
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@220148 c90b9560-bf6c-de11-be94-00142212c4b1
2006-09-17 21:18:50 +00:00
tony2001
b5cecfd421 add some more error messages
nuke dead code
use new parameter parsing API
update tests


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@220147 c90b9560-bf6c-de11-be94-00142212c4b1
2006-09-17 21:14:53 +00:00
tony2001
57f518d804 add tests
remove file missing in unrar 3.6.8


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@218973 c90b9560-bf6c-de11-be94-00142212c4b1
2006-08-28 12:24:49 +00:00
tony2001
0ed5106066 prepare for 0.3.1-beta
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@218972 c90b9560-bf6c-de11-be94-00142212c4b1
2006-08-28 12:21:16 +00:00
tony2001
473e865b38 update unrar to version 3.6.8
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@218970 c90b9560-bf6c-de11-be94-00142212c4b1
2006-08-28 12:19:04 +00:00
tony2001
b08d2ebc66 update changelog
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@216052 c90b9560-bf6c-de11-be94-00142212c4b1
2006-07-10 09:29:10 +00:00
tony2001
198fda108f fix PHP4 build
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@216051 c90b9560-bf6c-de11-be94-00142212c4b1
2006-07-10 09:03:48 +00:00
tony2001
a745071a2a update unrar to version 3.6.6
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@216048 c90b9560-bf6c-de11-be94-00142212c4b1
2006-07-10 08:38:22 +00:00
tony2001
6e5f90d038 prepare to 0.3.0
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@214300 c90b9560-bf6c-de11-be94-00142212c4b1
2006-06-06 08:07:44 +00:00
tony2001
45ac56f43b initialize internal structs
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@212385 c90b9560-bf6c-de11-be94-00142212c4b1
2006-05-03 21:39:21 +00:00
tony2001
c3913f5ee9 prepare to 0.3
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@212351 c90b9560-bf6c-de11-be94-00142212c4b1
2006-05-03 13:29:00 +00:00
tony2001
289e63250b add two more flags
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@212350 c90b9560-bf6c-de11-be94-00142212c4b1
2006-05-03 13:27:36 +00:00
tony2001
9b7245f2ba update unrar to 3.6.2
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@212349 c90b9560-bf6c-de11-be94-00142212c4b1
2006-05-03 13:26:34 +00:00
tony2001
a4f66e2dca fix/add .cvsignore files
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@205800 c90b9560-bf6c-de11-be94-00142212c4b1
2006-01-23 14:01:22 +00:00
tony2001
5ec39978bc nuke unused vars
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@205799 c90b9560-bf6c-de11-be94-00142212c4b1
2006-01-23 13:59:14 +00:00
tony2001
34652b09b2 don't use commandline when built as library
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@205798 c90b9560-bf6c-de11-be94-00142212c4b1
2006-01-23 13:58:51 +00:00
tony2001
905a30a02d reorganize sources
one more attempt to fix win32 build


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@205795 c90b9560-bf6c-de11-be94-00142212c4b1
2006-01-23 13:05:54 +00:00
fmk
355edc6bf5 Add missing list.cpp to source list
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@201052 c90b9560-bf6c-de11-be94-00142212c4b1
2005-11-22 17:33:42 +00:00
fmk
1ba294df92 Remove unused code blocks that breaks win32 builds
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@201051 c90b9560-bf6c-de11-be94-00142212c4b1
2005-11-22 17:33:11 +00:00
tony2001
c85047e54c update changelog
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@198129 c90b9560-bf6c-de11-be94-00142212c4b1
2005-10-10 19:27:33 +00:00
tony2001
5cbc4174f7 update bundled unrar to version 3.5.4
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@198128 c90b9560-bf6c-de11-be94-00142212c4b1
2005-10-10 19:26:35 +00:00
fmk
c3d082f6b3 Make sure the config file is loaded so HAVE_RAR is defined before it's checked.
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@187510 c90b9560-bf6c-de11-be94-00142212c4b1
2005-06-02 19:15:32 +00:00
wez
884f7db326 macro already includes these, maybe this will fix the rar dll?
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@187494 c90b9560-bf6c-de11-be94-00142212c4b1
2005-06-02 12:45:57 +00:00
tony2001
d5b4779393 *sigh*
I don't understand Windo$e..


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@183663 c90b9560-bf6c-de11-be94-00142212c4b1
2005-04-05 14:05:16 +00:00
tony2001
a0021aa3c2 fix build with HEAD
# why it worked nice before, I wonder?


git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@180383 c90b9560-bf6c-de11-be94-00142212c4b1
2005-02-21 20:19:42 +00:00
fmk
80af4abe5a fix debug build on win32
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@174922 c90b9560-bf6c-de11-be94-00142212c4b1
2004-12-16 20:23:12 +00:00
tony2001
890f103f50 release 0.2
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@173958 c90b9560-bf6c-de11-be94-00142212c4b1
2004-12-02 13:06:58 +00:00
edink
101fddb80a Older nmake does't like double backslashed in the path
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@173404 c90b9560-bf6c-de11-be94-00142212c4b1
2004-11-23 20:48:08 +00:00
tony2001
8a59dd703c add .cvsignore
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@172293 c90b9560-bf6c-de11-be94-00142212c4b1
2004-11-08 21:34:45 +00:00
tony2001
7a18c6a556 fix small shared module build issue
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@167972 c90b9560-bf6c-de11-be94-00142212c4b1
2004-09-04 12:53:45 +00:00
tony2001
c1a3d3d0a7 add OS constants
git-svn-id: http://svn.php.net/repository/pecl/rar/trunk@167966 c90b9560-bf6c-de11-be94-00142212c4b1
2004-09-04 12:21:50 +00:00
346 changed files with 43288 additions and 14857 deletions

88
.clang-format Normal file
View File

@@ -0,0 +1,88 @@
---
# Formatting style for php-rar C source files.
# Does NOT apply to unrar/ (see unrar/.clang-format).
Language: Cpp
BasedOnStyle: LLVM
# Indentation: real tabs, width 4 (matches vim modeline: noet sw=4 ts=4)
UseTab: Always
TabWidth: 4
IndentWidth: 4
ContinuationIndentWidth: 4
# Disable line-length wrapping to preserve hand-formatted long lines
ColumnLimit: 0
# Brace style:
# - Functions: brace on its own line (Allman)
# - Structs/unions/enums/extern "C": brace attached (K&R)
# - Control statements: brace attached (K&R)
# - else/else if: on its own line (after closing })
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: true
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
# Preserve indentation of preprocessor directives (# include, # define inside #ifdef)
IndentPPDirectives: AfterHash
PPIndentWidth: 1
# Pointer star attached to variable name: char *ptr
PointerAlignment: Right
DerivePointerAlignment: false
# Spaces
SpaceBeforeParens: ControlStatements
SpaceAfterCStyleCast: true
SpacesInParentheses: false
SpaceInEmptyParentheses: false
SpaceBeforeAssignmentOperators: true
# Don't align backslashes in multi-line macros (just 1 space before \)
AlignEscapedNewlines: DontAlign
# ZEND_BEGIN/END_ARG_INFO_EX act as block delimiters so ZEND_ARG_INFO lines
# inside them keep their indentation.
MacroBlockBegin: "^ZEND_BEGIN_ARG_INFO"
MacroBlockEnd: "^ZEND_END_ARG_INFO"
# Align continuation arguments after opening paren; when ( is last on the line,
# fall back to a block indent (ContinuationIndentWidth).
AlignAfterOpenBracket: Align
# Preserve existing include order
SortIncludes: Never
# case labels are indented one level inside switch
IndentCaseLabels: true
# Don't collapse or expand short constructs
AllowShortBlocksOnASingleLine: Never
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
# Alignment: leave hand-aligned blocks alone
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignTrailingComments: false
# Blank lines
MaxEmptyLinesToKeep: 2
KeepEmptyLinesAtTheStartOfBlocks: true

27
.github/docker-image-shas.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
# Docker image SHA lock file.
# Maps image tags to their multi-arch OCI index digests (amd64 + arm64).
# Regenerate with: .github/scripts/update-docker-shas.sh
datadog/dd-appsec-php-ci:
php-7.0-debug: "sha256:0a9aaeaf79bd4c578eac6dedabf6ac131537266f44562158ce67fdb37c794916"
php-7.0-release-zts: "sha256:4bb5fac6fbd3124234d062328c68f6c51027aa95f13e4e8b14afd7c8de518ec6"
php-7.1-debug: "sha256:500007ad057d9e71b2bb9079a2f8ba3f1ecfbb26d112db69e17d6007b4e857b5"
php-7.1-release-zts: "sha256:d997b9f99c28967872bd0949f8572b089daaadb6ceaa1e856ccc76e07e2ba6b7"
php-7.2-debug: "sha256:4c5f111f8e84fcb7dcc9e3cc13e1277d0702b04cd33286ce33db885485d1f025"
php-7.2-release-zts: "sha256:634b857d74c3d77b88986ceb088be2dd5bc30151bc08c2b536443984e6659d6e"
php-7.3-debug: "sha256:efa81f79783097478a434578226fe9a3b8fe84abda33168034aaea60c197c73b"
php-7.3-release-zts: "sha256:c713df299596a9615f88cfe73c29b0a1f9faf32e5e6fa62fa07ee839313cd57e"
php-7.4-debug: "sha256:b8a9e982179189122d73feb896c1a1e8578a92fc9a023dabc825f45db8299c22"
php-7.4-release-zts: "sha256:6492e3334e722b106352180ec9f0cbee8dd81f008e3537d03f4b8da3522f49e1"
php-8.0-debug: "sha256:900ceae7487db1e3652de2880c181e572fdf053673bcda8ff47abf664ff74d39"
php-8.0-release-zts: "sha256:b6243199f6aea0792a97583c9036f0b191ad9efb96ea337632fbaca76289a4da"
php-8.1-debug: "sha256:1a1e5b44cf043e59768c65fd7c94aaefdacde5fa96d83102d35db11ad86f24c6"
php-8.1-release-zts: "sha256:5b8a269b4228d9191420059daef820b660110be0aca6776557924172fd1ff0c8"
php-8.2-debug: "sha256:52ad14560672fc8c5130f5758bbee3fa401bc1d35b412f4a230c6258143291a5"
php-8.2-release-zts: "sha256:cb143d915b394f16a2d78018765705460f3d1b788fdd2a90ef50fad5f8f5918c"
php-8.3-debug: "sha256:bb6df08160126374d3d9247428928aa19a9c2b2429c98356650199b85ae20212"
php-8.3-release-zts: "sha256:e58e25a017f75df82691d408b8cb70453875ff36718e295ee8c6653a0f117331"
php-8.4-debug: "sha256:15045688f6986f4625b1507a7f4be6104e7bbb88caf877f1611463b929f2bca2"
php-8.4-release-zts: "sha256:8e0ac25a3306b4b9f692c593b8a509cc789c2e001ce52682928065a92c880136"
php-8.5-debug: "sha256:bd0170331b34fb469e29d00b19b20fb88b726160f76df274a1bdc3a27ac18d30"
php-8.5-release-zts: "sha256:e071b2095da55bd24686209422f43a01c65acfc6021f04156d9fb43fd3d4d426"

35
.github/scripts/build-and-test.sh vendored Executable file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env bash
# Build the extension and run the test suite.
# Expected to run inside a datadog/dd-appsec-php-ci container from the repo root.
set -euo pipefail
# Clean up artifacts from any previous build so stale objects don't survive a
# PHP-version switch (safe in CI where the workspace is always fresh).
if [ -f Makefile ]; then
make -f Makefile distclean
fi
phpize
./configure --with-php-config="$(which php-config)"
make -f Makefile -j"$(nproc)"
# The generated Makefile silences and ignores errors on the `if` commands;
# undo that so test failures surface properly.
sed -i 's/-@if/@if/' Makefile
ret=0
TEST_PHP_EXECUTABLE="$(which php)" \
TEST_PHP_JUNIT=report.xml \
REPORT_EXIT_STATUS=1 \
NO_INTERACTION=1 \
TESTS="--set-timeout 300 --show-diff" \
make -f Makefile test || ret=$?
found=$(find tests -name '*.mem' | wc -l)
if [ "$found" -gt 0 ]; then
echo "Found $found memory leak(s):"
find tests -name '*.mem' -print -exec cat {} \;
ret=1
fi
exit "$ret"

52
.github/scripts/update-docker-shas.sh vendored Executable file
View File

@@ -0,0 +1,52 @@
#!/usr/bin/env bash
# Refresh docker-image-shas.yml with current OCI index digests.
# The index digest covers all platforms (amd64 + arm64); Docker resolves the
# right platform image from it at pull time.
# Justfile and tests.yml read from docker-image-shas.yml directly — no patching needed.
set -euo pipefail
IMAGE="datadog/dd-appsec-php-ci"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOCK_FILE="$SCRIPT_DIR/../docker-image-shas.yml"
TAGS=(
php-7.0-debug php-7.0-release-zts
php-7.1-debug php-7.1-release-zts
php-7.2-debug php-7.2-release-zts
php-7.3-debug php-7.3-release-zts
php-7.4-debug php-7.4-release-zts
php-8.0-debug php-8.0-release-zts
php-8.1-debug php-8.1-release-zts
php-8.2-debug php-8.2-release-zts
php-8.3-debug php-8.3-release-zts
php-8.4-debug php-8.4-release-zts
php-8.5-debug php-8.5-release-zts
)
get_index_digest() {
# The top-level "digest" field in the Hub tags API is the manifest-list
# (OCI index) digest, not a per-platform image digest.
curl -fsSL "https://hub.docker.com/v2/repositories/${IMAGE}/tags/$1" \
| python3 -c "import sys,json; print(json.load(sys.stdin)['digest'])"
}
# Collect all digests first so we fail fast before touching any file.
declare -A DIGESTS
for tag in "${TAGS[@]}"; do
echo "Fetching $tag ..." >&2
DIGESTS[$tag]=$(get_index_digest "$tag")
done
# ── Update docker-image-shas.yml ─────────────────────────────────────────────
{
echo "# Docker image SHA lock file."
echo "# Maps image tags to their multi-arch OCI index digests (amd64 + arm64)."
echo "# Regenerate with: .github/scripts/update-docker-shas.sh"
echo ""
echo "${IMAGE}:"
for tag in "${TAGS[@]}"; do
printf " %-20s \"%s\"\n" "${tag}:" "${DIGESTS[$tag]}"
done
} > "$LOCK_FILE"
echo "Updated $LOCK_FILE" >&2

123
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,123 @@
name: Release binaries
on:
push:
tags:
- 'v[0-9]*.[0-9]*.[0-9]*'
permissions:
contents: read
jobs:
check-version:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check version consistency
run: |
TAG_VERSION="${GITHUB_REF_NAME#v}"
HEADER_VERSION=$(grep -oP '(?<=#define PHP_RAR_VERSION ")[^"]+' php_rar.h)
PACKAGE_VERSION=$(python3 -c "
import xml.etree.ElementTree as ET
t = ET.parse('package.xml')
ns = {'p': 'http://pear.php.net/dtd/package-2.0'}
print(t.find('p:version/p:release', ns).text)
")
echo "Tag version: $TAG_VERSION"
echo "Header version: $HEADER_VERSION"
echo "Package version: $PACKAGE_VERSION"
if [ "$TAG_VERSION" != "$HEADER_VERSION" ]; then
echo "ERROR: Tag version ($TAG_VERSION) does not match PHP_RAR_VERSION in php_rar.h ($HEADER_VERSION)"
exit 1
fi
if [ "$TAG_VERSION" != "$PACKAGE_VERSION" ]; then
echo "ERROR: Tag version ($TAG_VERSION) does not match version in package.xml ($PACKAGE_VERSION)"
exit 1
fi
echo "All versions match: $TAG_VERSION"
create-draft-release:
needs: [check-version]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-tags: 'true'
ref: ${{ github.ref }}
- name: Create draft release from tag
env:
GH_TOKEN: ${{ github.token }}
run: gh release create "${{ github.ref_name }}" --title "${{ github.ref_name }}" --draft --notes-from-tag
windows-extension-matrix:
needs: [create-draft-release]
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.extension-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@v4
- name: Get the extension matrix
id: extension-matrix
uses: php/php-windows-builder/extension-matrix@v1
with:
php-version-list: '8.0, 8.1, 8.2, 8.3, 8.4, 8.5'
windows-build:
needs: [windows-extension-matrix]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.windows-extension-matrix.outputs.matrix) }}
steps:
- uses: actions/checkout@v4
- name: Build the extension for Windows
uses: php/php-windows-builder/extension@v1
with:
php-version: ${{ matrix.php-version }}
arch: ${{ matrix.arch }}
ts: ${{ matrix.ts }}
args: --enable-rar=shared
test-runner: run-tests-rar.php
windows-release:
needs: [windows-build]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Upload artifacts to the release
uses: php/php-windows-builder/release@v1
with:
release: ${{ github.ref_name }}
token: ${{ secrets.GITHUB_TOKEN }}
draft: 'true'
pecl-package:
needs: [create-draft-release]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
tools: pecl
- name: Build PECL package
run: pecl package
- name: Upload PECL package to release
env:
GH_TOKEN: ${{ github.token }}
run: gh release upload "${{ github.ref_name }}" rar-*.tgz

92
.github/workflows/tests.yml vendored Normal file
View File

@@ -0,0 +1,92 @@
name: Tests
on:
push:
pull_request:
jobs:
check-dev-version:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
steps:
- uses: actions/checkout@v4
- name: Check PHP_RAR_VERSION ends in -dev
run: |
HEADER_VERSION=$(grep -oP '(?<=#define PHP_RAR_VERSION ")[^"]+' php_rar.h)
echo "Header version: $HEADER_VERSION"
if [[ "$HEADER_VERSION" != *-dev ]]; then
echo "ERROR: PHP_RAR_VERSION ($HEADER_VERSION) does not end in -dev on master"
exit 1
fi
generate-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@v4
- id: set-matrix
run: |
python3 <<'EOF'
import yaml, json, os
with open('.github/docker-image-shas.yml') as f:
data = yaml.safe_load(f)
image = 'datadog/dd-appsec-php-ci'
includes = []
for tag, sha in data[image].items():
# tag: "php-7.0-debug" or "php-7.0-release-zts"
ver, variant = tag[len('php-'):].split('-', 1)
includes.append({'php': ver, 'variant': variant, 'image_sha': sha})
with open(os.environ['GITHUB_OUTPUT'], 'a') as f:
f.write('matrix=' + json.dumps({'include': includes}) + '\n')
EOF
linux:
name: PHP ${{ matrix.php }} (${{ matrix.variant }})
needs: generate-matrix
runs-on: ubuntu-latest
container:
image: datadog/dd-appsec-php-ci@${{ matrix.image_sha }}
options: --user root
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build and test
run: bash .github/scripts/build-and-test.sh
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results-php${{ matrix.php }}-${{ matrix.variant }}
path: report.xml
windows:
name: Windows PHP 8.1 TS
runs-on: windows-2022
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build and test
uses: php/php-windows-builder/extension@v1
with:
php-version: '8.1'
arch: x64
ts: ts
args: --enable-rar=shared
test-runner: ${{ github.workspace }}/run-tests-rar.php
test-workers: 1
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results-windows-php8.1-ts
path: '*.xml'

54
.gitignore vendored Normal file
View File

@@ -0,0 +1,54 @@
*.o
*.lo
/run-tests.php
/tests/*.sh
/tests/*.exp
/tests/*.diff
/tests/*.log
/tests/*.php
/tests/*.out
/tests/*.mem
/modules
/missing
/.deps
/.libs
/Makefile
/Makefile.fragments
/Makefile.global
/Makefile.objects
/acinclude.m4
/aclocal.m4
/autom4te.cache
/build
/config.guess
/config.h
/config.h.in
/config.h.in~
/config.log
/config.nice
/config.status
/config.sub
/configure
/configure.in
/configure.ac
/install-sh
/intl.la
/libtool
/mkinstalldirs
/ltmain.sh
/.cproject
/.project
/.settings
/pecl-rar.*
/rar.la
*.autosave
/unrar/.libs
/tmp-php.ini
/php-rar.creator.user
/compile_commands.json
/.clangd
/report.xml
/.worktrees
*.dep
/configure~
/.cache/

View File

@@ -1 +1,2 @@
Antony Dovgal
RAR
Antony Dovgal, Gustavo Lopes

View File

113
Justfile Normal file
View File

@@ -0,0 +1,113 @@
# Build and test inside the matching CI Docker image.
# Image SHAs are read from .github/docker-image-shas.yml (multi-arch OCI index digests).
# To refresh SHAs: .github/scripts/update-docker-shas.sh
# ── Images ────────────────────────────────────────────────────────────────────
_base := "datadog/dd-appsec-php-ci@"
_shas := ".github/docker-image-shas.yml"
image_7_0_debug := _base + `grep 'php-7.0-debug:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_7_0_release_zts := _base + `grep 'php-7.0-release-zts:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_7_1_debug := _base + `grep 'php-7.1-debug:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_7_1_release_zts := _base + `grep 'php-7.1-release-zts:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_7_2_debug := _base + `grep 'php-7.2-debug:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_7_2_release_zts := _base + `grep 'php-7.2-release-zts:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_7_3_debug := _base + `grep 'php-7.3-debug:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_7_3_release_zts := _base + `grep 'php-7.3-release-zts:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_7_4_debug := _base + `grep 'php-7.4-debug:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_7_4_release_zts := _base + `grep 'php-7.4-release-zts:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_8_0_debug := _base + `grep 'php-8.0-debug:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_8_0_release_zts := _base + `grep 'php-8.0-release-zts:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_8_1_debug := _base + `grep 'php-8.1-debug:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_8_1_release_zts := _base + `grep 'php-8.1-release-zts:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_8_2_debug := _base + `grep 'php-8.2-debug:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_8_2_release_zts := _base + `grep 'php-8.2-release-zts:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_8_3_debug := _base + `grep 'php-8.3-debug:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_8_3_release_zts := _base + `grep 'php-8.3-release-zts:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_8_4_debug := _base + `grep 'php-8.4-debug:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_8_4_release_zts := _base + `grep 'php-8.4-release-zts:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_8_5_debug := _base + `grep 'php-8.5-debug:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_8_5_release_zts := _base + `grep 'php-8.5-release-zts:' .github/docker-image-shas.yml | cut -d'"' -f2`
_run := "docker run --rm --entrypoint bash -v \"$PWD:/workspace\" -w /workspace --user root"
# ── Default ───────────────────────────────────────────────────────────────────
default:
@just --list
# ── Individual targets ────────────────────────────────────────────────────────
test-7_0-debug:
{{_run}} {{image_7_0_debug}} .github/scripts/build-and-test.sh
test-7_0-release-zts:
{{_run}} {{image_7_0_release_zts}} .github/scripts/build-and-test.sh
test-7_1-debug:
{{_run}} {{image_7_1_debug}} .github/scripts/build-and-test.sh
test-7_1-release-zts:
{{_run}} {{image_7_1_release_zts}} .github/scripts/build-and-test.sh
test-7_2-debug:
{{_run}} {{image_7_2_debug}} .github/scripts/build-and-test.sh
test-7_2-release-zts:
{{_run}} {{image_7_2_release_zts}} .github/scripts/build-and-test.sh
test-7_3-debug:
{{_run}} {{image_7_3_debug}} .github/scripts/build-and-test.sh
test-7_3-release-zts:
{{_run}} {{image_7_3_release_zts}} .github/scripts/build-and-test.sh
test-7_4-debug:
{{_run}} {{image_7_4_debug}} .github/scripts/build-and-test.sh
test-7_4-release-zts:
{{_run}} {{image_7_4_release_zts}} .github/scripts/build-and-test.sh
test-8_0-debug:
{{_run}} {{image_8_0_debug}} .github/scripts/build-and-test.sh
test-8_0-release-zts:
{{_run}} {{image_8_0_release_zts}} .github/scripts/build-and-test.sh
test-8_1-debug:
{{_run}} {{image_8_1_debug}} .github/scripts/build-and-test.sh
test-8_1-release-zts:
{{_run}} {{image_8_1_release_zts}} .github/scripts/build-and-test.sh
test-8_2-debug:
{{_run}} {{image_8_2_debug}} .github/scripts/build-and-test.sh
test-8_2-release-zts:
{{_run}} {{image_8_2_release_zts}} .github/scripts/build-and-test.sh
test-8_3-debug:
{{_run}} {{image_8_3_debug}} .github/scripts/build-and-test.sh
test-8_3-release-zts:
{{_run}} {{image_8_3_release_zts}} .github/scripts/build-and-test.sh
test-8_4-debug:
{{_run}} {{image_8_4_debug}} .github/scripts/build-and-test.sh
test-8_4-release-zts:
{{_run}} {{image_8_4_release_zts}} .github/scripts/build-and-test.sh
test-8_5-debug:
{{_run}} {{image_8_5_debug}} .github/scripts/build-and-test.sh
test-8_5-release-zts:
{{_run}} {{image_8_5_release_zts}} .github/scripts/build-and-test.sh
# ── Per-version aggregates (sequential to avoid workspace conflicts) ───────────
test-7_0: test-7_0-debug test-7_0-release-zts
test-7_1: test-7_1-debug test-7_1-release-zts
test-7_2: test-7_2-debug test-7_2-release-zts
test-7_3: test-7_3-debug test-7_3-release-zts
test-7_4: test-7_4-debug test-7_4-release-zts
test-8_0: test-8_0-debug test-8_0-release-zts
test-8_1: test-8_1-debug test-8_1-release-zts
test-8_2: test-8_2-debug test-8_2-release-zts
test-8_3: test-8_3-debug test-8_3-release-zts
test-8_4: test-8_4-debug test-8_4-release-zts
test-8_5: test-8_5-debug test-8_5-release-zts
# ── All Linux targets ─────────────────────────────────────────────────────────
test-linux: test-7_0 test-7_1 test-7_2 test-7_3 test-7_4 test-8_0 test-8_1 test-8_2 test-8_3 test-8_4 test-8_5

68
LICENSE Normal file
View File

@@ -0,0 +1,68 @@
--------------------------------------------------------------------
The PHP License, version 3.01
Copyright (c) 1999 - 2010 The PHP Group. All rights reserved.
--------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, is permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The name "PHP" must not be used to endorse or promote products
derived from this software without prior written permission. For
written permission, please contact group@php.net.
4. Products derived from this software may not be called "PHP", nor
may "PHP" appear in their name, without prior written permission
from group@php.net. You may indicate that your software works in
conjunction with PHP by saying "Foo for PHP" instead of calling
it "PHP Foo" or "phpfoo"
5. The PHP Group may publish revised and/or new versions of the
license from time to time. Each version will be given a
distinguishing version number.
Once covered code has been published under a particular version
of the license, you may always continue to use it under the terms
of that version. You may also choose to use such covered code
under the terms of any subsequent version of the license
published by the PHP Group. No one other than the PHP Group has
the right to modify the terms applicable to covered code created
under this License.
6. Redistributions of any form whatsoever must retain the following
acknowledgment:
"This product includes PHP software, freely available from
<http://www.php.net/software/>".
THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------
This software consists of voluntary contributions made by many
individuals on behalf of the PHP Group.
The PHP Group can be contacted via Email at group@php.net.
For more information on the PHP Group and the PHP project,
please see <http://www.php.net>.
PHP includes the Zend Engine, freely available at
<http://www.zend.com>.

5
Makefile.frag Normal file
View File

@@ -0,0 +1,5 @@
.PHONY: replace-run-tests
replace-run-tests:
cp run-tests-rar.php run-tests.php
test: replace-run-tests

31
README.md Normal file
View File

@@ -0,0 +1,31 @@
PHP extension for reading RAR archives using the bundled UnRAR library.
This extension uses a modified version of the UnRAR library. The UnRAR library
is an official open-source library by RARLabs, an auto generated subset of the
RAR codebase. It is available from http://www.rarlab.com/rar_add.htm
Please note that it has a more restrictive license than the PHP bindings,
barring using it to re-create the RAR compression algorithm. See
unrar/LICENSE.txt for details.
Some modifications have been applied to the UnRAR library, mainly to allow
streaming extraction of files without using threads.
## Installation
### With PECL
```sh
pecl install rar
```
Then add `extension=rar` to your `php.ini`.
### With PIE
[PIE](https://github.com/php/pie) is the modern replacement for PECL, available from PHP 8.1+.
```sh
pie install rar
```
PIE automatically adds the extension to your `php.ini`.

31
composer.json Normal file
View File

@@ -0,0 +1,31 @@
{
"name": "cataphract/rar",
"type": "php-ext",
"description": "PHP extension for reading RAR archives using bundled unRAR library",
"license": "PHP-3.01",
"authors": [
{
"name": "Gustavo Lopes",
"email": "cataphract@php.net",
"role": "lead"
},
{
"name": "Antony Dovgal",
"email": "tony@daylessday.org",
"role": "developer"
}
],
"require": {
"php": "^7.0 || ^8.0"
},
"replace": {
"ext-rar": "*"
},
"support": {
"source": "https://github.com/cataphract/php-rar"
},
"php-ext": {
"extension-name": "rar",
"download-url-method": ["pre-packaged-binary", "composer-default"]
}
}

View File

@@ -2,30 +2,73 @@ dnl $Id$
dnl config.m4 for extension rar
PHP_ARG_ENABLE(rar, whether to enable rar support,
[ --enable-rar Enable rar support])
[ --enable-rar Enable rar support])
unrar_sources="unrar/rar.cpp unrar/strlist.cpp unrar/strfn.cpp \
unrar/pathfn.cpp unrar/int64.cpp unrar/savepos.cpp \
unrar/global.cpp unrar/file.cpp unrar/filefn.cpp \
unrar/filcreat.cpp unrar/archive.cpp unrar/arcread.cpp \
unrar/unicode.cpp unrar/system.cpp unrar/isnt.cpp \
unrar/crypt.cpp unrar/crc.cpp unrar/rawread.cpp \
unrar/encname.cpp unrar/resource.cpp unrar/match.cpp \
unrar/timefn.cpp unrar/rdwrfn.cpp unrar/consio.cpp \
unrar/options.cpp unrar/ulinks.cpp unrar/errhnd.cpp \
unrar/rarvm.cpp unrar/rijndael.cpp unrar/getbits.cpp \
unrar/sha1.cpp unrar/extinfo.cpp unrar/extract.cpp \
unrar/volume.cpp unrar/find.cpp \
unrar/unpack.cpp unrar/cmddata.cpp unrar/dll.cpp \
unrar/filestr.cpp unrar/recvol.cpp unrar/rs.cpp \
unrar/scantree.cpp"
unrar_sources="unrar/sha256.cpp unrar/qopen.cpp \
unrar/blake2s.cpp unrar/recvol.cpp \
unrar/headers.cpp unrar/match.cpp \
unrar/find.cpp \
unrar/resource.cpp \
unrar/pathfn.cpp \
unrar/dll.cpp unrar/threadpool.cpp unrar/volume.cpp \
unrar/unpack.cpp \
unrar/extract.cpp unrar/errhnd.cpp \
unrar/crc.cpp unrar/rijndael.cpp unrar/crypt.cpp \
unrar/rawread.cpp \
unrar/rs.cpp unrar/smallfn.cpp \
unrar/isnt.cpp unrar/rar.cpp unrar/consio.cpp \
unrar/scantree.cpp unrar/archive.cpp unrar/strfn.cpp \
unrar/strlist.cpp \
unrar/getbits.cpp unrar/hash.cpp \
unrar/filestr.cpp \
unrar/extinfo.cpp unrar/ui.cpp unrar/rarvm.cpp \
unrar/timefn.cpp unrar/sha1.cpp \
unrar/rdwrfn.cpp unrar/rs16.cpp unrar/cmddata.cpp \
unrar/extractchunk.cpp unrar/system.cpp \
unrar/unicode.cpp unrar/filcreat.cpp \
unrar/arcread.cpp unrar/filefn.cpp \
unrar/global.cpp unrar/list.cpp \
unrar/encname.cpp unrar/file.cpp \
unrar/secpassword.cpp unrar/options.cpp \
unrar/largepage.cpp"
AC_LANG_PUSH([C++])
cxxflags_null=""
AC_DEFUN([CXXC_FLAG_CHECK],
[
ac_saved_cxxflags="$CXXFLAGS"
CXXFLAGS="$1 -Werror"
flag_to_add=m4_default([$2],[$1])
AC_MSG_CHECKING([whether the C++ compiler supports $1])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([])],
[AC_MSG_RESULT([yes])]
[cxxflags_null="$cxxflags_null $flag_to_add"],
[AC_MSG_RESULT([no])]
)
CXXFLAGS="$ac_saved_cxxflags"
])
CXXC_FLAG_CHECK([-Wparentheses], [-Wno-parentheses])
CXXC_FLAG_CHECK([-Wswitch], [-Wno-switch])
CXXC_FLAG_CHECK([-Wdangling-else], [-Wno-dangling-else])
CXXC_FLAG_CHECK([-Wunused-function], [-Wno-unused-function])
CXXC_FLAG_CHECK([-Wunused-variable], [-Wno-unused-variable])
CXXC_FLAG_CHECK([-Wsign-compare], [-Wno-sign-compare])
CXXC_FLAG_CHECK([-Wmisleading-indentation], [-Wno-misleading-indentation])
AC_LANG_POP([C++])
extra_cxxflags="$cxxflags_null"
echo "EXTRA_CXXFLAGS := \$(EXTRA_CXXFLAGS) $extra_cxxflags" >> Makefile.fragments
cat Makefile.frag >> Makefile.fragments
INCLUDES=`echo "$INCLUDES" | sed 's/-I/-isystem /g'`
if test "$PHP_RAR" != "no"; then
PHP_REQUIRE_CXX
AC_DEFINE(HAVE_RAR, 1, [Whether you have rar support])
PHP_SUBST(RAR_SHARED_LIBADD)
PHP_ADD_BUILD_DIR($ext_builddir/unrar)
PHP_SUBST(RAR_SHARED_LIBADD)
PHP_REQUIRE_CXX()
PHP_ADD_LIBRARY_WITH_PATH(stdc++, "", RAR_SHARED_LIBADD)
PHP_NEW_EXTENSION(rar, rar.cpp $unrar_sources, $ext_shared,,-I@ext_srcdir@/unrar)
PHP_NEW_EXTENSION(rar, rar.c rar_error.c rararch.c rarentry.c rar_stream.c rar_navigation.c rar_time.c $unrar_sources, $ext_shared,,-DRARDLL -DSILENT -Wno-write-strings -Wall -fPIC -fvisibility=hidden -I@ext_srcdir@/unrar)
PHP_ADD_BUILD_DIR($ext_builddir/unrar)
fi

View File

@@ -4,25 +4,35 @@
ARG_ENABLE("rar", "Rar support", "no");
if (PHP_RAR != "no") {
EXTENSION("rar", "rar.cpp");
ADD_SOURCES(configure_module_dirname + "unrar/", "rar.cpp \
strlist.cpp strfn.cpp pathfn.cpp int64.cpp \
savepos.cpp global.cpp file.cpp filefn.cpp \
filcreat.cpp archive.cpp arcread.cpp unicode.cpp \
system.cpp isnt.cpp crypt.cpp crc.cpp \
rawread.cpp encname.cpp resource.cpp match.cpp \
timefn.cpp rdwrfn.cpp consio.cpp options.cpp \
ulinks.cpp errhnd.cpp rarvm.cpp rijndael.cpp \
getbits.cpp sha1.cpp extinfo.cpp extract.cpp \
volume.cpp find.cpp unpack.cpp cmddata.cpp \
dll.cpp filestr.cpp recvol.cpp rs.cpp \
scantree.cpp", "rar");
EXTENSION("rar", "rar.c rar_error.c rararch.c rarentry.c rar_stream.c rar_navigation.c rar_time.c", PHP_RAR_SHARED, "/DRARDLL /DSILENT /EHsc /D_WSTDIO_DEFINED");
ADD_SOURCES(configure_module_dirname + "/unrar",
"sha256.cpp qopen.cpp \
blake2s.cpp recvol.cpp \
headers.cpp match.cpp \
find.cpp \
resource.cpp \
pathfn.cpp \
dll.cpp threadpool.cpp volume.cpp \
unpack.cpp \
extract.cpp errhnd.cpp \
crc.cpp rijndael.cpp crypt.cpp \
rawread.cpp \
rs.cpp smallfn.cpp \
isnt.cpp consio.cpp \
scantree.cpp archive.cpp strfn.cpp \
strlist.cpp \
getbits.cpp hash.cpp \
filestr.cpp \
extinfo.cpp ui.cpp rarvm.cpp \
timefn.cpp sha1.cpp \
rdwrfn.cpp rs16.cpp cmddata.cpp \
extractchunk.cpp system.cpp \
unicode.cpp filcreat.cpp \
arcread.cpp filefn.cpp \
global.cpp list.cpp \
encname.cpp file.cpp \
secpassword.cpp options.cpp \
largepage.cpp motw.cpp", "rar");
if (!PHP_RAR_SHARED) {
ADD_DEF_FILE(configure_module_dirname + "unrar\\dll.def");
}
AC_DEFINE("HAVE_RAR", 1, "Rar support");
}

62
extflow.txt Normal file
View File

@@ -0,0 +1,62 @@
(some information is outdated)
rar_open/RarArchive::open()
gives
RarArchive object
-
. stores 2 open data structs (are used to tell the lib e.g. which file to open and the lib in return stores some data in them)
- list_open_data has open mode RAR_OM_LIST_INCSPLIT and is used to list the contents of the archive
- extract_open_data has open mode RAR_OM_EXTRACT and is used by RarEntry::extract
. stores one opened archive handle, opened with the list_open_data struct. This handle remains
open until the archive is closed or the object is destroyed
. a RarArchive object is considered closed when the opened archive handle created here is set to NULL
rar_list()/RarArchive::getEntries()
gives
RarEntry objects
-
. CALL _rar_list_files, which fills the lazy cache rar->entries by using the opened archive handle to retrieve ALL the RarHeaderDataEx headers
. CALL _rar_raw_entries_to_files to turn the rar->entries RarHeaderDataEx headers into zvals
- in turn, _rar_raw_entries_to_files creates the zval and sets the property that holds the zval reference to the RarArchive object (see below)
- calculates the packed size by summing over all the headers that concern each file (a file may have more than one header in case there are volumes)
- then CALLs _rar_entry_to_zval with the last header for each file and the packed size so that it can fill the remaining properties
. each of the RarEntry objects store a zval referencing the RarArchive object. The RarArchive object is not destroyed until all its spawned RarEntry objects are destroyed (it can however be closed)
rar_entry_get()/RarArchive::getEntry()
gives
RarEntry object
-
. CALL _rar_list_files, if it's necessary to fill the lazy cache rar->entries
. CALL _rar_raw_entries_to_files, which traverses rar->entries until it finds the request filename, the header(s) are then converted into one zval
. again, the RarEntry object stores a reference to the RarArchive object
RarArchive traversal with an iterator
gives
RarEntry objects (one at a time)
-
. iterator creation CALLs_rar_list_files, if it's necessary to fill the lazy cache rar->entries
. iterator stores the index (with respect to the rar->entries array) of the last header in rar->entries that is to be read (starts with 0)
. iterator CALLs _rar_raw_entries_to_files, which here stops after reading each file and advances the index
RarEntry::extract()
extracts the file
-
. uses the extract_open_data that's stored in the parent RarArchive object
. makes a shallow copy of parent RarArchive's rar->cb_userdata, eventually modified with the given file password.
. passes them to _rar_find_file to open the file with RAR_OM_EXTRACT and skip to the desired entry
. extracts the file
. closes the rar handle
RarEntry::getStream()
obtains stream
-
. CALL php_stream_rar_open with the archive name (obtained from parent RarArchive object's extract_open_data->ArcName), the filename of the entry and a shallow copy of parent RarArchive's rar->cb_userdata, eventually modified with the given file password.
. in turn, php_stream_rar_open CALLs _rar_find_file with a brand new rar open data struct with RAR_OM_EXTRACT. _rar_find_file opens the RAR archive and skips to the desired entry
. the resulting stream has no connection to the original RarArchive object or to the RarEntry object
. the rar archive is not closed until the stream is destroyed or closed

View File

@@ -1,161 +1,641 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<package>
<name>rar</name>
<summary>rar extension</summary>
<description>
Rar is a powerful and effective archiver, which was
created by Eugene Roshal and became rather popular quite fast.
This extension gives you possibility to read Rar archives.
</description>
<license>PHP License</license>
<maintainers>
<maintainer>
<user>tony2001</user>
<name>Antony Dovgal</name>
<email>tony2001@phpclub.net</email>
</maintainer>
</maintainers>
<release>
<version>0.1</version>
<date>2004-06-11</date>
<state>alpha</state>
<notes>
1) Initial release
</notes>
</release>
<filelist>
<dir role="src" name="/">
<file role="doc">CREDITS</file>
<file role="doc">example.php</file>
<?xml version="1.0" encoding="UTF-8"?>
<package packagerversion="1.5.4" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
http://pear.php.net/dtd/tasks-1.0.xsd
http://pear.php.net/dtd/package-2.0
http://pear.php.net/dtd/package-2.0.xsd">
<name>rar</name>
<channel>pecl.php.net</channel>
<summary>rar extension</summary>
<description>PHP extension for reading RAR archives using bundled unRAR library.
</description>
<file role="src">config.m4</file>
<file role="src">php_rar.h</file>
<file role="src">rar.cpp</file>
<dir role="src" name="/unrar/">
<lead>
<name>Gustavo Lopes</name>
<user>cataphract</user>
<email>cataphract@php.net</email>
<active>yes</active>
</lead>
<file role="doc">LICENSE.txt</file>
<file role="doc">README.txt</file>
<developer>
<name>Antony Dovgal</name>
<user>tony2001</user>
<email>tony@daylessday.org</email>
<active>no</active>
</developer>
<file role="src">arccmt.cpp</file>
<file role="src">archive.cpp</file>
<file role="src">archive.hpp</file>
<file role="src">arcread.cpp</file>
<file role="src">array.hpp</file>
<file role="src">beosea.cpp</file>
<file role="src">cmddata.cpp</file>
<file role="src">cmddata.hpp</file>
<file role="src">coder.cpp</file>
<file role="src">coder.hpp</file>
<file role="src">compress.hpp</file>
<file role="src">consio.cpp</file>
<file role="src">consio.hpp</file>
<file role="src">crc.cpp</file>
<file role="src">crc.hpp</file>
<file role="src">crypt.cpp</file>
<file role="src">crypt.hpp</file>
<file role="src">dll.cpp</file>
<file role="src">dll.def</file>
<file role="src">dll.hpp</file>
<file role="src">encname.cpp</file>
<file role="src">encname.hpp</file>
<file role="src">errhnd.cpp</file>
<file role="src">errhnd.hpp</file>
<file role="src">extinfo.cpp</file>
<file role="src">extinfo.hpp</file>
<file role="src">extract.cpp</file>
<file role="src">extract.hpp</file>
<file role="src">filcreat.cpp</file>
<file role="src">filcreat.hpp</file>
<file role="src">file.cpp</file>
<file role="src">filefn.cpp</file>
<file role="src">filefn.hpp</file>
<file role="src">file.hpp</file>
<file role="src">filestr.cpp</file>
<file role="src">filestr.hpp</file>
<file role="src">find.cpp</file>
<file role="src">find.hpp</file>
<file role="src">getbits.cpp</file>
<file role="src">getbits.hpp</file>
<file role="src">global.cpp</file>
<file role="src">global.hpp</file>
<file role="src">headers.hpp</file>
<file role="src">int64.cpp</file>
<file role="src">int64.hpp</file>
<file role="src">isnt.cpp</file>
<file role="src">isnt.hpp</file>
<file role="src">list.cpp</file>
<file role="src">list.hpp</file>
<file role="src">loclang.hpp</file>
<file role="src">log.cpp</file>
<file role="src">log.hpp</file>
<file role="src">match.cpp</file>
<file role="src">match.hpp</file>
<file role="src">memfree.hpp</file>
<file role="src">model.cpp</file>
<file role="src">model.hpp</file>
<file role="src">msc.dep</file>
<file role="src">options.cpp</file>
<file role="src">options.hpp</file>
<file role="src">os2ea.cpp</file>
<file role="src">os.hpp</file>
<file role="src">pathfn.cpp</file>
<file role="src">pathfn.hpp</file>
<file role="src">rar.cpp</file>
<file role="src">rardefs.hpp</file>
<file role="src">rarfn.hpp</file>
<file role="src">rar.hpp</file>
<file role="src">rarlang.hpp</file>
<file role="src">raros.hpp</file>
<file role="src">rartypes.hpp</file>
<file role="src">rarvm.cpp</file>
<file role="src">rarvm.hpp</file>
<file role="src">rarvmtbl.cpp</file>
<file role="src">rawread.cpp</file>
<file role="src">rawread.hpp</file>
<file role="src">rdwrfn.cpp</file>
<file role="src">rdwrfn.hpp</file>
<file role="src">recvol.cpp</file>
<file role="src">recvol.hpp</file>
<file role="src">resource.cpp</file>
<file role="src">resource.hpp</file>
<file role="src">rijndael.cpp</file>
<file role="src">rijndael.hpp</file>
<file role="src">rs.cpp</file>
<file role="src">rs.hpp</file>
<file role="src">savepos.cpp</file>
<file role="src">savepos.hpp</file>
<file role="src">scantree.cpp</file>
<file role="src">scantree.hpp</file>
<file role="src">sha1.cpp</file>
<file role="src">sha1.hpp</file>
<file role="src">smallfn.cpp</file>
<file role="src">smallfn.hpp</file>
<file role="src">strfn.cpp</file>
<file role="src">strfn.hpp</file>
<file role="src">strlist.cpp</file>
<file role="src">strlist.hpp</file>
<file role="src">suballoc.cpp</file>
<file role="src">suballoc.hpp</file>
<file role="src">system.cpp</file>
<file role="src">system.hpp</file>
<file role="src">timefn.cpp</file>
<file role="src">timefn.hpp</file>
<file role="src">ulinks.cpp</file>
<file role="src">ulinks.hpp</file>
<file role="src">unicode.cpp</file>
<file role="src">unicode.hpp</file>
<file role="src">unpack15.cpp</file>
<file role="src">unpack20.cpp</file>
<file role="src">unpack.cpp</file>
<file role="src">unpack.hpp</file>
<file role="src">uowners.cpp</file>
<file role="src">version.hpp</file>
<file role="src">volume.cpp</file>
<file role="src">volume.hpp</file>
<file role="src">win32acl.cpp</file>
<file role="src">win32stm.cpp</file>
</dir>
</dir>
</filelist>
<date>2026-03-08</date>
<time>20:00:00</time>
<version>
<release>4.3.0</release>
<api>4.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://www.php.net/license">PHP License</license>
<notes>- Add PHP 8.1, 8.2, 8.3, 8.4, 8.5 support.
- Drop PHP 5 support; minimum PHP version is now 7.0.
- Update bundled unrar to 7.2.4.
- Fix Windows bug
</notes>
<contents>
<dir name="/">
<dir name="tests">
<file role="test" name="001.phpt"/>
<file role="test" name="002.phpt"/>
<file role="test" name="003.phpt"/>
<file role="test" name="004.phpt"/>
<file role="test" name="4mb.rar"/>
<file role="test" name="005.phpt"/>
<file role="test" name="006.phpt"/>
<file role="test" name="007.phpt"/>
<file role="test" name="008.phpt"/>
<file role="test" name="009.phpt"/>
<file role="test" name="010.phpt"/>
<file role="test" name="011.phpt"/>
<file role="test" name="012.phpt"/>
<file role="test" name="013.phpt"/>
<file role="test" name="014.phpt"/>
<file role="test" name="015.phpt"/>
<file role="test" name="016.phpt"/>
<file role="test" name="017.phpt"/>
<file role="test" name="018.phpt"/>
<file role="test" name="019.phpt"/>
<file role="test" name="020.phpt"/>
<file role="test" name="021.phpt"/>
<file role="test" name="022.phpt"/>
<file role="test" name="023.phpt"/>
<file role="test" name="024.phpt"/>
<file role="test" name="025.phpt"/>
<file role="test" name="026.phpt"/>
<file role="test" name="027.phpt"/>
<file role="test" name="028.phpt"/>
<file role="test" name="029.phpt"/>
<file role="test" name="030.phpt"/>
<file role="test" name="031.phpt"/>
<file role="test" name="032.phpt"/>
<file role="test" name="033.phpt"/>
<file role="test" name="034.phpt"/>
<file role="test" name="035.phpt"/>
<file role="test" name="036.phpt"/>
<file role="test" name="037.phpt"/>
<file role="test" name="038.phpt"/>
<file role="test" name="039.phpt"/>
<file role="test" name="040.phpt"/>
<file role="test" name="041.phpt"/>
<file role="test" name="042.phpt"/>
<file role="test" name="043.phpt"/>
<file role="test" name="044.phpt"/>
<file role="test" name="045.phpt"/>
<file role="test" name="046.phpt"/>
<file role="test" name="047.phpt"/>
<file role="test" name="048.phpt"/>
<file role="test" name="049.phpt"/>
<file role="test" name="050.phpt"/>
<file role="test" name="051.phpt"/>
<file role="test" name="052.phpt"/>
<file role="test" name="053.phpt"/>
<file role="test" name="054.phpt"/>
<file role="test" name="055.phpt"/>
<file role="test" name="056.phpt"/>
<file role="test" name="057.phpt"/>
<file role="test" name="058.phpt"/>
<file role="test" name="059.phpt"/>
<file role="test" name="060.phpt"/>
<file role="test" name="061.phpt"/>
<file role="test" name="062.phpt"/>
<file role="test" name="063.phpt"/>
<file role="test" name="064.phpt"/>
<file role="test" name="065.phpt"/>
<file role="test" name="066.phpt"/>
<file role="test" name="067.phpt"/>
<file role="test" name="070.phpt"/>
<file role="test" name="071.phpt"/>
<file role="test" name="072.phpt"/>
<file role="test" name="073.phpt"/>
<file role="test" name="074.phpt"/>
<file role="test" name="075.phpt"/>
<file role="test" name="076.phpt"/>
<file role="test" name="077.phpt"/>
<file role="test" name="078.phpt"/>
<file role="test" name="079.phpt"/>
<file role="test" name="080.phpt"/>
<file role="test" name="081.phpt"/>
<file role="test" name="082.phpt"/>
<file role="test" name="083.phpt"/>
<file role="test" name="084.phpt"/>
<file role="test" name="085.phpt"/>
<file role="test" name="086.phpt"/>
<file role="test" name="087.phpt"/>
<file role="test" name="088.phpt"/>
<file role="test" name="089.phpt"/>
<file role="test" name="090.phpt"/>
<file role="test" name="091.phpt"/>
<file role="test" name="092.phpt"/>
<file role="test" name="093.phpt"/>
<file role="test" name="094.phpt"/>
<file role="test" name="095.phpt"/>
<file role="test" name="096.phpt"/>
<file role="test" name="097.phpt"/>
<file role="test" name="098.phpt"/>
<file role="test" name="099.phpt"/>
<file role="test" name="100.phpt"/>
<file role="test" name="101.phpt"/>
<file role="test" name="102.phpt"/>
<file role="test" name="103.phpt"/>
<file role="test" name="104.phpt"/>
<file role="test" name="106.phpt"/>
<file role="test" name="107.phpt"/>
<file role="test" name="108.phpt"/>
<file role="test" name="109.phpt"/>
<file role="test" name="110.phpt"/>
<file role="test" name="111.phpt"/>
<file role="test" name="112.phpt"/>
<file role="test" name="113.phpt"/>
<file role="test" name="114.phpt"/>
<file role="test" name="115.phpt"/>
<file role="test" name="commented.rar"/>
<file role="test" name="corrupted.rar"/>
<file role="test" name="directories.rar"/>
<file role="test" name="dirlink_unix.rar"/>
<file role="test" name="dirs_and_extra_headers.rar"/>
<file role="test" name="empty_file.rar"/>
<file role="test" name="encrypted_headers.rar"/>
<file role="test" name="encrypted_only_files.rar"/>
<file role="test" name="garbage.part03.rar"/>
<file role="test" name="latest_winrar.rar"/>
<file role="test" name="linux_rar.rar"/>
<file role="test" name="multi.part1.rar"/>
<file role="test" name="multi.part2.rar"/>
<file role="test" name="multi.part3.rar"/>
<file role="test" name="multi_broken.part1.rar"/>
<file role="test" name="php8compat.php.inc"/>
<file role="test" name="rar_notrar.rar"/>
<file role="test" name="rar_unicode.rar"/>
<file role="test" name="repeated_name.rar"/>
<file role="test" name="secret-crypted-none.rar"/>
<file role="test" name="secret-none.rar"/>
<file role="test" name="solid.rar"/>
<file role="test" name="sparsefiles_rar.rar"/>
<file role="test" name="store_method.rar"/>
<file role="test" name="rar5-links.rar"/>
<file role="test" name="rar5_multi.part1.rar"/>
<file role="test" name="rar5_multi.part2.rar"/>
</dir> <!-- /tests -->
<dir name="unrar">
<file name="acknow.txt" role="doc" />
<file name="arccmt.cpp" role="src" />
<file name="archive.cpp" role="src" />
<file name="archive.hpp" role="src" />
<file name="arcread.cpp" role="src" />
<file name="blake2s.cpp" role="src" />
<file name="blake2s.hpp" role="src" />
<file name="blake2s_sse.cpp" role="src" />
<file name="blake2sp.cpp" role="src" />
<file name="cmddata.cpp" role="src" />
<file name="cmddata.hpp" role="src" />
<file name="cmdfilter.cpp" role="src" />
<file name="cmdmix.cpp" role="src" />
<file name="coder.cpp" role="src" />
<file name="coder.hpp" role="src" />
<file name="compress.hpp" role="src" />
<file name="consio.cpp" role="src" />
<file name="consio.hpp" role="src" />
<file name="crc.cpp" role="src" />
<file name="crc.hpp" role="src" />
<file name="crypt.cpp" role="src" />
<file name="crypt.hpp" role="src" />
<file name="crypt1.cpp" role="src" />
<file name="crypt2.cpp" role="src" />
<file name="crypt3.cpp" role="src" />
<file name="crypt5.cpp" role="src" />
<file name="dll.cpp" role="src" />
<file name="dll.hpp" role="src" />
<file name="encname.cpp" role="src" />
<file name="encname.hpp" role="src" />
<file name="errhnd.cpp" role="src" />
<file name="errhnd.hpp" role="src" />
<file name="extinfo.cpp" role="src" />
<file name="extinfo.hpp" role="src" />
<file name="extract.cpp" role="src" />
<file name="extract.hpp" role="src" />
<file name="extractchunk.cpp" role="src" />
<file name="filcreat.cpp" role="src" />
<file name="filcreat.hpp" role="src" />
<file name="file.cpp" role="src" />
<file name="file.hpp" role="src" />
<file name="filefn.cpp" role="src" />
<file name="filefn.hpp" role="src" />
<file name="filestr.cpp" role="src" />
<file name="filestr.hpp" role="src" />
<file name="find.cpp" role="src" />
<file name="find.hpp" role="src" />
<file name="getbits.cpp" role="src" />
<file name="getbits.hpp" role="src" />
<file name="global.cpp" role="src" />
<file name="global.hpp" role="src" />
<file name="hardlinks.cpp" role="src" />
<file name="hash.cpp" role="src" />
<file name="hash.hpp" role="src" />
<file name="headers.cpp" role="src" />
<file name="headers.hpp" role="src" />
<file name="headers5.hpp" role="src" />
<file name="isnt.cpp" role="src" />
<file name="isnt.hpp" role="src" />
<file name="largepage.cpp" role="src" />
<file name="largepage.hpp" role="src" />
<file name="LICENSE.txt" role="doc" />
<file name="list.cpp" role="src" />
<file name="list.hpp" role="src" />
<file name="loclang.hpp" role="src" />
<file name="log.cpp" role="src" />
<file name="log.hpp" role="src" />
<file name="match.cpp" role="src" />
<file name="match.hpp" role="src" />
<file name="model.cpp" role="src" />
<file name="model.hpp" role="src" />
<file name="motw.cpp" role="src" />
<file name="motw.hpp" role="src" />
<file name="options.cpp" role="src" />
<file name="options.hpp" role="src" />
<file name="os.hpp" role="src" />
<file name="pathfn.cpp" role="src" />
<file name="pathfn.hpp" role="src" />
<file name="qopen.cpp" role="src" />
<file name="qopen.hpp" role="src" />
<file name="rar.cpp" role="src" />
<file name="rar.hpp" role="src" />
<file name="rardefs.hpp" role="src" />
<file name="rarlang.hpp" role="src" />
<file name="raros.hpp" role="src" />
<file name="rartypes.hpp" role="src" />
<file name="rarvm.cpp" role="src" />
<file name="rarvm.hpp" role="src" />
<file name="rawint.hpp" role="src" />
<file name="rawread.cpp" role="src" />
<file name="rawread.hpp" role="src" />
<file name="rdwrfn.cpp" role="src" />
<file name="rdwrfn.hpp" role="src" />
<file name="recvol3.cpp" role="src" />
<file name="recvol5.cpp" role="src" />
<file name="rs16.cpp" role="src" />
<file name="rs16.hpp" role="src" />
<file name="sha256.cpp" role="src" />
<file name="sha256.hpp" role="src" />
<file name="threadmisc.cpp" role="src" />
<file name="threadpool.cpp" role="src" />
<file name="threadpool.hpp" role="src" />
<file name="ui.cpp" role="src" />
<file name="ui.hpp" role="src" />
<file name="uicommon.cpp" role="src" />
<file name="uiconsole.cpp" role="src" />
<file name="uisilent.cpp" role="src" />
<file name="unpack30.cpp" role="src" />
<file name="unpack50.cpp" role="src" />
<file name="unpack50frag.cpp" role="src" />
<file name="unpack50mt.cpp" role="src" />
<file name="unpackinline.cpp" role="src" />
<file name="win32lnk.cpp" role="src" />
<file name="README.txt" role="doc" />
<file name="recvol.cpp" role="src" />
<file name="recvol.hpp" role="src" />
<file name="resource.cpp" role="src" />
<file name="resource.hpp" role="src" />
<file name="rijndael.cpp" role="src" />
<file name="rijndael.hpp" role="src" />
<file name="rs.cpp" role="src" />
<file name="rs.hpp" role="src" />
<file name="scantree.cpp" role="src" />
<file name="scantree.hpp" role="src" />
<file name="secpassword.cpp" role="src" />
<file name="secpassword.hpp" role="src" />
<file name="sha1.cpp" role="src" />
<file name="sha1.hpp" role="src" />
<file name="smallfn.cpp" role="src" />
<file name="smallfn.hpp" role="src" />
<file name="strfn.cpp" role="src" />
<file name="strfn.hpp" role="src" />
<file name="strlist.cpp" role="src" />
<file name="strlist.hpp" role="src" />
<file name="suballoc.cpp" role="src" />
<file name="suballoc.hpp" role="src" />
<file name="system.cpp" role="src" />
<file name="system.hpp" role="src" />
<file name="timefn.cpp" role="src" />
<file name="timefn.hpp" role="src" />
<file name="ulinks.cpp" role="src" />
<file name="unicode.cpp" role="src" />
<file name="unicode.hpp" role="src" />
<file name="unpack.cpp" role="src" />
<file name="unpack.hpp" role="src" />
<file name="unpack15.cpp" role="src" />
<file name="unpack20.cpp" role="src" />
<file name="uowners.cpp" role="src" />
<file name="version.hpp" role="src" />
<file name="volume.cpp" role="src" />
<file name="volume.hpp" role="src" />
<file name="win32acl.cpp" role="src" />
<file name="win32stm.cpp" role="src" />
</dir> <!-- /unrar -->
<file name="config.m4" role="src" />
<file name="config.w32" role="src" />
<file name="CREDITS" role="doc" />
<file name="LICENSE" role="doc" />
<file name="Makefile.frag" role="src" />
<file name="README.md" role="doc" />
<file name="example.php" role="doc" />
<file name="php_compat.h" role="src" />
<file name="php_rar.h" role="src" />
<file name="rar.c" role="src" />
<file name="rar_stream.c" role="src" />
<file name="rararch.c" role="src" />
<file name="rarentry.c" role="src" />
<file name="rar_error.c" role="src" />
<file name="rar_time.c" role="src" />
<file name="run-tests-rar.php" role="test" />
<file role="src" name="rar_navigation.c"/>
</dir> <!-- / -->
</contents>
<dependencies>
<required>
<php>
<min>7.0.0</min>
</php>
<pearinstaller>
<min>1.4.0</min>
</pearinstaller>
</required>
</dependencies>
<providesextension>rar</providesextension>
<extsrcrelease />
<changelog>
<release>
<version>
<release>4.3.0</release>
<api>4.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2026-03-08</date>
<notes>Changes in this version:
- Add PHP 8.1, 8.2, 8.3 support.
- Drop PHP 5 support; minimum PHP version is now 7.0.
- Update bundled unrar to 7.2.4.
- Fix segfault caused by uninitialized RARHeaderDataEx.
- Fix dll.cpp: don't propagate non-fatal ErrHandler errors as failures.
- Fix RAR5 chunk extraction spurious warning on Windows with multi-core CPUs.
- Migrate CI from Azure Pipelines/Appveyor to GitHub Actions.
</notes>
</release>
<release>
<version>
<release>4.2.0</release>
<api>4.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2020-12-06</date>
<notes>Changes in this version:
- Support PHP 8.
- Merge unrar 6.0.2.
- RarArchive implements IteratorAggregate (PHP 8 only).
</notes>
</release>
<release>
<version>
<release>4.1.0</release>
<api>4.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2020-10-11</date>
<notes>Changes in this version:
- Merge changes made to unrar up to version 5.5.6.
- Support PHP 7.2, PHP 7.3 and PHP 7.4.
- Update to unrar 5.9.4.
- Fix bug #76592: streaming unpacking of uncompressed files incomplete.
</notes>
</release>
<release>
<version>
<release>4.0.0</release>
<api>4.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2017-07-22</date>
<notes>Changes in this version:
- Added functions RarEntry::getRedirType(), RarEntry::isRedirectToDirectory() and RarEntry::getRedirTarget(), as well as the following constants on RarEntry: FSREDIR_UNIXSYMLINK, FSREDIR_WINSYMLINK, FSREDIR_JUNCTION, FSREDIR_HARDLINK and FSREDIR_FILECOPY.
- Changed stat handler to return UTC time for creation, modification and access time (does not work reliably on Windows).
- Fix cloning of RarArchive being allowed.
</notes>
</release>
<release>
<version>
<release>3.0.2</release>
<api>3.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2013-10-11</date>
<notes>Changes in this version:
- Fixed build with PHP 5.5.
- Upgraded bundled unrar to version 4.2.4.
</notes>
</release>
<release>
<version>
<release>3.0.1</release>
<api>3.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2012-07-29</date>
<notes>Changes in this version:
- Merge changes made to unrar up to version 4.2.2.
- Fix leak in PHP >= 5.3.11, = 5.4.0 and compile error in master.
- Fix some tests failing if TZ != Europe/Lisbon.
- Fix bad pointer in an error message.
- Added test for bug #59939 (can't reproduce).
</notes>
</release>
<release>
<version>
<release>2.0.0</release>
<api>2.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2010-04-20</date>
<notes>Changes with respect to release 2.0.0RC1:
- Fixed infinite loop when opening RAR archive missing a volume (later report in bug #17177).
- Fixed bug #17025 (changed the name of method RarArchive::list into RarArchive::getEntries). If backwards compatibility with the release candidate is required, RarArchive::list can be reintroduced by defining RAR_ARCHIVE_LIST_ALIAS.
Incompatible changes with respect to release 1.0.0:
PHP Support:
- Support for PHP 4.3 dropped. PHP 5.2.x or 5.3.x is required.
API backwards incompatible changes:
- Handles unicode filenames (uses UTF-8 external encoding). The file names inside the RAR archives are always returned in UTF-8. This will probably break your scripts.
- Calling rar_close/RarArchive::close() invalidates RarEntry objects (actually, only extraction is forbidden, but don't rely on it).
For the other changes, see the changelog for version 2.0.0RC1.
</notes>
</release>
<release>
<version>
<release>2.0.0RC1</release>
<api>2.0.0RC1</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2010-01-17</date>
<license>PHP License and UnRar license</license>
<notes>Changes in respect to release 1.0.0:
PHP SUPPORT:
- Support for PHP 4.3 dropped. PHP 5.2.x or 5.3.x is required.
API BACKWARDS INCOMPATIBLE CHANGES:
- Handles unicode filenames (uses UTF-8 external encoding). The file names inside the RAR archives are always returned in UTF-8. This will probably break your scripts.
- Calling rar_close/RarArchive::close() invalidates RarEntry objects (actually, only extraction is forbidden, but don't rely on it).
API backwards compatible changes:
- Supports streaming from RAR archives. See RarEntry::getStream() method.
- Added a bunch of constants to RarEntry.
- Added RarEntry::__toString() method.
- Added RarEntry::isDirectory() method.
- Added RarEntry::isEncrypted() method.
- Added OOP interface for rar_* functions with the RarArchive class.
- Added rar_comment_get/RarArchive::getComment().
- Added RarArchive::isSolid()/rar_solid_is().
- Added RarArchive::__toString() method.
- Added RarException class.
- Exception throwing for expectable errors can be turned on by calling RarException::setUsingExceptions(). To check whether exception throwing is turned on, RarException::isUsingExceptions() can be used.
Bug fixes:
- Fixed by PECL bug #8821 (relative paths not working).
- Fixed PECL bug #9470 (wrong CRC on multi-volume archives).
- Fixed PECL bug #9649 (rar_close() not closing file descriptors if there were undestroyed RarEntry objects)
- Fixed volumes opened with middle volumes showing files continued from previous volume with incorrect packed and unpacked sizes.
- Fixed bug in UnRAR library that could cause a read out of buffer bounds on some corrupted RAR files.
- Fixed RarEntry::getPackedSize() and RarEntry::getUnpackedSize() giving incorrect results for files > 2 GiB. Still, on platforms with 32-bit integers, MAX_INT will be returned for such files, othwerwise the correct value is given.
Other changes:
- Updated bundled UnRAR library to version 3.9.7 (RAR 3.9.1).
- Changed bundled UnRAR library to allow partial file extraction.
- All RarEntry properties are now private. This doesn't break the API because those properties were never part of the contract.
- rar_open gives more detailed error messages on failure.
- Extension now uses extended UnRAR library structures.
- Added arginfo.
- Added a bunch of tests.
- A lot of refactoring and compilation as C, not C++.
</notes>
</release>
<release>
<version>
<release>1.0.0</release>
<api>1.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2008-02-26</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>- Upgraded bundled UnRar to version 3.7.8.
- Updated source code to use new parameter parsing API.
- Fixed PECL bug #9002 (rar_list invalidates rar resource)
- Fixed PECL bug #11430 (rar_extract() doesn't close handles gracefully)
- rar_open() now throws an error when failed to open the specified file.
</notes>
</release>
<release>
<version>
<release>0.3.1</release>
<api>0.3.1</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2006-08-28</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>- Updated bundled unrar to version 3.6.8.
- Fixed PHP4 compatibility.
</notes>
</release>
<release>
<version>
<release>0.3.0</release>
<api>0.3.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2006-06-06</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>- Updated bundled unrar to version 3.6.2 (fixes compile errors with GCC4).
- Several minor fixes.
</notes>
</release>
<release>
<version>
<release>0.2</release>
<api>0.2</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2004-12-02</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>1) Added open_basedir and safe_mode checks.
2) Fixed Win32 build issues (thanks to Edin).
Currently only 5.x builds are available.
3) Added OS constants.
4) Fixed 0 bugs. There are no bugs, wee =)
</notes>
</release>
<release>
<version>
<release>0.1</release>
<api>0.1</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2004-06-11</date>
<license uri="http://www.php.net/license">PHP License</license>
<notes>1) Initial release
</notes>
</release>
</changelog>
</package>
<!--
vim:et:ts=1:sw=1
-->

11
php-rar.config Normal file
View File

@@ -0,0 +1,11 @@
// Add predefined macros for your project here. For example:
// #define THE_ANSWER 42
#define RARDLL 1
#define HAVE_CONFIG_H 1
#define _Float32 float
#define _Float32x float
#define _Float64 double
#define _Float64x double
#define _Float128 long double
#define _Float128x long double
#define _BITS_FLOATN_H

1
php-rar.creator Normal file
View File

@@ -0,0 +1 @@
[General]

161
php-rar.files Normal file
View File

@@ -0,0 +1,161 @@
config.h
php_compat.h
php_compat.h
php_rar.h
rar.c
rar_error.c
rar_navigation.c
rar_stream.c
rar_time.c
rararch.c
rarentry.c
unrar/arccmt.cpp
unrar/archive.cpp
unrar/archive.hpp
unrar/arcread.cpp
unrar/array.hpp
unrar/blake2s.cpp
unrar/blake2s.hpp
unrar/blake2s_sse.cpp
unrar/blake2sp.cpp
unrar/cmddata.cpp
unrar/cmddata.hpp
unrar/cmdfilter.cpp
unrar/cmdmix.cpp
unrar/coder.cpp
unrar/coder.hpp
unrar/compress.hpp
unrar/consio.cpp
unrar/consio.hpp
unrar/crc.cpp
unrar/crc.hpp
unrar/crypt.cpp
unrar/crypt.hpp
unrar/crypt1.cpp
unrar/crypt2.cpp
unrar/crypt3.cpp
unrar/crypt5.cpp
unrar/dll.cpp
unrar/dll.hpp
unrar/encname.cpp
unrar/encname.hpp
unrar/errhnd.cpp
unrar/errhnd.hpp
unrar/extinfo.cpp
unrar/extinfo.hpp
unrar/extract.cpp
unrar/extract.hpp
unrar/extractchunk.cpp
unrar/filcreat.cpp
unrar/filcreat.hpp
unrar/file.cpp
unrar/file.hpp
unrar/filefn.cpp
unrar/filefn.hpp
unrar/filestr.cpp
unrar/filestr.hpp
unrar/find.cpp
unrar/find.hpp
unrar/getbits.cpp
unrar/getbits.hpp
unrar/global.cpp
unrar/global.hpp
unrar/hardlinks.cpp
unrar/hash.cpp
unrar/hash.hpp
unrar/headers.cpp
unrar/headers.hpp
unrar/headers5.hpp
unrar/isnt.cpp
unrar/isnt.hpp
unrar/list.cpp
unrar/list.hpp
unrar/loclang.hpp
unrar/log.cpp
unrar/log.hpp
unrar/match.cpp
unrar/match.hpp
unrar/model.cpp
unrar/model.hpp
unrar/options.cpp
unrar/options.hpp
unrar/os.hpp
unrar/pathfn.cpp
unrar/pathfn.hpp
unrar/qopen.cpp
unrar/qopen.hpp
unrar/rar.cpp
unrar/rar.hpp
unrar/rardefs.hpp
unrar/rarlang.hpp
unrar/raros.hpp
unrar/rartypes.hpp
unrar/rarvm.cpp
unrar/rarvm.hpp
unrar/rarvmtbl.cpp
unrar/rawint.hpp
unrar/rawread.cpp
unrar/rawread.hpp
unrar/rdwrfn.cpp
unrar/rdwrfn.hpp
unrar/recvol.cpp
unrar/recvol.hpp
unrar/recvol3.cpp
unrar/recvol5.cpp
unrar/resource.cpp
unrar/resource.hpp
unrar/rijndael.cpp
unrar/rijndael.hpp
unrar/rs.cpp
unrar/rs.hpp
unrar/rs16.cpp
unrar/rs16.hpp
unrar/savepos.hpp
unrar/scantree.cpp
unrar/scantree.hpp
unrar/secpassword.cpp
unrar/secpassword.hpp
unrar/sha1.cpp
unrar/sha1.hpp
unrar/sha256.cpp
unrar/sha256.hpp
unrar/smallfn.cpp
unrar/smallfn.hpp
unrar/strfn.cpp
unrar/strfn.hpp
unrar/strlist.cpp
unrar/strlist.hpp
unrar/suballoc.cpp
unrar/suballoc.hpp
unrar/system.cpp
unrar/system.hpp
unrar/threadmisc.cpp
unrar/threadpool.cpp
unrar/threadpool.hpp
unrar/timefn.cpp
unrar/timefn.hpp
unrar/ui.cpp
unrar/ui.hpp
unrar/uicommon.cpp
unrar/uiconsole.cpp
unrar/uisilent.cpp
unrar/ulinks.cpp
unrar/ulinks.hpp
unrar/unicode.cpp
unrar/unicode.hpp
unrar/unpack.cpp
unrar/unpack.hpp
unrar/unpack15.cpp
unrar/unpack20.cpp
unrar/unpack30.cpp
unrar/unpack50.cpp
unrar/unpack50frag.cpp
unrar/unpack50mt.cpp
unrar/unpackinline.cpp
unrar/uowners.cpp
unrar/version.hpp
unrar/volume.cpp
unrar/volume.hpp
unrar/win32acl.cpp
unrar/win32lnk.cpp
unrar/win32stm.cpp

4
php-rar.includes Normal file
View File

@@ -0,0 +1,4 @@
/home/glopes/repos/php-src/Zend
/home/glopes/repos/php-src/TSRM
/home/glopes/repos/php-src/main
/home/glopes/repos/php-src

54
php_compat.h Normal file
View File

@@ -0,0 +1,54 @@
#include <php.h>
#if PHP_MAJOR_VERSION >= 8
# define TSRMLS_DC
# define TSRMLS_D
# define TSRMLS_CC
# define TSRMLS_C
# define TSRMLS_FETCH()
# define IS_CALLABLE_STRICT 0
# define zend_qsort zend_sort
# define ZV_TO_THIS_FOR_HANDLER(zv) (Z_OBJ_P(zv))
typedef zend_object handler_this_t;
#else
# define ZV_TO_THIS_FOR_HANDLER(zv) (zv)
typedef zval handler_this_t;
#endif
typedef zend_object* rar_obj_ref;
#define rar_zval_add_ref(ppzv) zval_add_ref(*ppzv)
#define ZVAL_ALLOC_DUP(dst, src) \
do { \
dst = (zval*) emalloc(sizeof(zval)); \
ZVAL_DUP(dst, src); \
} while (0)
#define RAR_RETURN_STRINGL(s, l, duplicate) \
do { \
RETVAL_STRINGL(s, l); \
if (duplicate == 0) { \
efree(s); \
} \
return; \
} while (0)
#define RAR_ZVAL_STRING(z, s, duplicate) \
do { \
ZVAL_STRING(z, s); \
if (duplicate == 0) { \
efree(s); \
} \
} while (0)
typedef size_t zpp_s_size_t;
#define MAKE_STD_ZVAL(zv_p) \
do { \
(zv_p) = emalloc(sizeof(zval)); \
ZVAL_NULL(zv_p); \
} while (0)
#define INIT_ZVAL(zv) ZVAL_UNDEF(&zv)
#define ZEND_ACC_FINAL_CLASS ZEND_ACC_FINAL

264
php_rar.h
View File

@@ -15,23 +15,44 @@
| **** WARNING **** |
| |
| This module makes use of unRAR - free utility for RAR archives. |
| It's license states, that you MUST NOT use it's code to develop |
| Its license states, that you MUST NOT use its code to develop |
| a RAR (WinRAR) compatible archiver. |
| Please, read unRAR license for full information. |
| unRAR & RAR copyrights are owned by Eugene Roshal |
+----------------------------------------------------------------------+
| Author: Antony Dovgal <tony2001@phpclub.net> |
| Author: Antony Dovgal <tony@daylessday.org> |
| Author: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
/* TODO: metadata block reading */
/* TODO: correct support for symlinks inside RAR files. This includes:
* - Respecting PHP_STREAM_URL_STAT_LINK in the url_stater
* - Following the symlinks when asked to open one inside the RAR
* Sym link support on windows will be more complicated */
/* TODO: add support for opening RAR files in a persisten fashion */
/* TODO: consider making struct rar opaque, outside rararch.c only
* RarEntry::extract/getStream access the fields */
/* TODO: consider using a php memory/tmpfile stream to serve as buffer for
* rar file streams */
/* TODO: improve RAR archive cache key for url_stater/dir_opener, so that it
* can detect file modification */
/* TODO: make configurable the capacity of the url_stater/dir_opener cache */
/* TODO: optimize _rar_nav_directory_match with the depth */
/* TODO: tests with truncated RAR archive (for which _rar_list_files fails) */
#ifndef PHP_RAR_H
#define PHP_RAR_H
#include <php.h>
extern zend_module_entry rar_module_entry;
#define phpext_rar_ptr &rar_module_entry
#define PHP_RAR_VERSION "4.3.1-dev"
#ifdef PHP_WIN32
#define PHP_RAR_API __declspec(dllexport)
#else
@@ -42,38 +63,239 @@ extern zend_module_entry rar_module_entry;
#include "TSRM.h"
#endif
#include "php_compat.h"
/* causes linking errors (multiple definitions) in functions
that were requested inlining but were not inlined by the compiler */
/* #include "unrar/rar.hpp */
/* only these includes are necessary anyway: */
#include "unrar/raros.hpp"
#include "unrar/rartypes.hpp"
/* no need to reinclude windows.h or new.h */
#define LEAN_RAR_INCLUDES
#include "unrar/os.hpp"
#include "unrar/dll.hpp"
#include "unrar/version.hpp"
/* These are in unrar/headers.hpp, but that header depends on several other */
/* clang-format off */
enum HOST_SYSTEM {
HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4,
HOST_BEOS=5,HOST_MAX
};
enum FILE_SYSTEM_REDIRECT {
FSREDIR_NONE=0, FSREDIR_UNIXSYMLINK, FSREDIR_WINSYMLINK, FSREDIR_JUNCTION,
FSREDIR_HARDLINK, FSREDIR_FILECOPY
};
/* clang-format on */
/* maximum comment size if 64KB */
#define RAR_MAX_COMMENT_SIZE 65536
/* clang-format off */
typedef struct _rar_cb_user_data {
char *password; /* can be NULL */
zval *callable; /* can be NULL */
} rar_cb_user_data;
typedef struct rar {
rar_obj_ref obj_ref;
struct _rar_entries *entries;
struct RAROpenArchiveDataEx *list_open_data;
struct RAROpenArchiveDataEx *extract_open_data;
/* archive handle opened with RAR_OM_LIST_INCSPLIT open mode */
void *arch_handle;
/* user data to pass the RAR callback */
rar_cb_user_data cb_userdata;
int allow_broken;
} rar_file_t;
/* clang-format on */
/* Misc */
# if defined(__GNUC__) || defined(__clang__)
# define ARR_SIZE(arr) \
(sizeof(arr) / sizeof((arr)[0]) + \
0 * sizeof(char[1 - 2 * __builtin_types_compatible_p( \
__typeof__(arr), __typeof__(&(arr)[0]))]))
# else
# define ARR_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
# endif
# define RAR_TSRMLS_TC
#define RAR_RETNULL_ON_ARGS() \
if (zend_parse_parameters_none() == FAILURE) { \
RETURN_NULL(); \
}
/* Per-request cache or make last the duration of the PHP lifespan?
* - per-request advantages: we can re-use rar_open and store close RarArchive
* objects. We store either pointers to the objects directly and manipulate
* the refcount in the store or we store zvals. Either way, we must decrement
* the refcounts on request shutdown. Also, the memory usage is best kept
* in check because the memory is freed after each request.
* - per PHP lifespan advantages: more cache hits. We can also re-use rar_open,
* but then we have to copy rar->entries and rar->entries_idx into
* persistently allocated buffers since the RarArchive objects cannot be made
* persistent themselves.
*
* I'll go with per-request and store zval pointers with a cache key that
* considers filename, modificaion time and stream context (currently only
* filename).
* I'll also go with a FIFO eviction policy because it's simpler to implement
* (just delete the first element of the HashTable).
*/
typedef struct _rar_contents_cache {
int max_size;
HashTable *data; /* persistent HashTable, will hold rar_cache_entry */
int hits;
int misses;
/* args: cache key, cache key size, cached object) */
void (*put)(const char *, uint, zval * RAR_TSRMLS_TC);
zval *(*get)(const char *, uint, zval * RAR_TSRMLS_TC);
} rar_contents_cache;
/* Module globals, currently used for dir wrappers cache */
ZEND_BEGIN_MODULE_GLOBALS(rar)
rar_contents_cache contents_cache;
ZEND_END_MODULE_GLOBALS(rar)
ZEND_EXTERN_MODULE_GLOBALS(rar);
#ifdef ZTS
# define RAR_G(v) TSRMG(rar_globals_id, zend_rar_globals *, v)
#else
# define RAR_G(v) (rar_globals.v)
#endif
#if !defined(HAVE_STRNLEN) || !HAVE_STRNLEN
size_t _rar_strnlen(const char *s, size_t maxlen);
# define strnlen _rar_strnlen
#else
# define _rar_strnlen strnlen
#endif
/* rar.c */
PHP_MINIT_FUNCTION(rar);
PHP_MSHUTDOWN_FUNCTION(rar);
PHP_RINIT_FUNCTION(rar);
PHP_RSHUTDOWN_FUNCTION(rar);
PHP_MINFO_FUNCTION(rar);
PHP_FUNCTION(rar_bogus_ctor);
void _rar_wide_to_utf(const wchar_t *src, char *dest, size_t dest_size);
void _rar_utf_to_wide(const char *src, wchar_t *dest, size_t dest_size);
void _rar_destroy_userdata(rar_cb_user_data *udata);
int _rar_find_file(struct RAROpenArchiveDataEx *open_data, /* IN */
const char *const utf_file_name, /* IN */
rar_cb_user_data *cb_udata, /* IN, must be managed outside */
void **arc_handle, /* OUT: where to store rar archive handle */
int *found, /* OUT */
struct RARHeaderDataEx *header_data /* OUT, can be null */
);
int _rar_find_file_w(struct RAROpenArchiveDataEx *open_data, /* IN */
const wchar_t *const file_name, /* IN */
rar_cb_user_data *cb_udata, /* IN, must be managed outside */
void **arc_handle, /* OUT: where to store rar archive handle */
int *found, /* OUT */
struct RARHeaderDataEx *header_data /* OUT, can be null */
);
int _rar_find_file_p(struct RAROpenArchiveDataEx *open_data, /* IN */
size_t position, /* IN */
rar_cb_user_data *cb_udata, /* IN, must be managed outside */
void **arc_handle, /* OUT: where to store rar archive handle */
int *found, /* OUT */
struct RARHeaderDataEx *header_data /* OUT, can be null */
);
int CALLBACK _rar_unrar_callback(UINT msg, LPARAM UserData, LPARAM P1, LPARAM P2);
/* rar_error.c */
extern zend_class_entry *rarexception_ce_ptr;
int _rar_handle_error(int errcode TSRMLS_DC);
int _rar_handle_error_ex(const char *preamble, int errcode TSRMLS_DC);
void _rar_handle_ext_error(const char *format TSRMLS_DC, ...);
int _rar_using_exceptions(TSRMLS_D);
const char * _rar_error_to_string(int errcode);
void minit_rarerror(TSRMLS_D);
/* rar_navigation.c */
int _rar_list_files(rar_file_t *rar TSRMLS_DC);
void _rar_delete_entries(rar_file_t *rar TSRMLS_DC);
size_t _rar_entry_count(rar_file_t *rar);
/* entry search API {{{ */
typedef struct _rar_find_output {
int found;
size_t position;
struct RARHeaderDataEx * header;
zend_ulong packed_size;
int eof;
} rar_find_output;
#define RAR_SEARCH_INDEX 0x01U
#define RAR_SEARCH_TRAVERSE 0x01U
#define RAR_SEARCH_DIRECTORY 0x02U
#define RAR_SEARCH_NAME 0x02U
void _rar_entry_search_start(rar_file_t *rar,
unsigned mode,
rar_find_output **state TSRMLS_DC);
void _rar_entry_search_end(rar_find_output *state);
void _rar_entry_search_seek(rar_find_output *state, size_t pos);
void _rar_entry_search_rewind(rar_find_output *state);
void _rar_entry_search_advance(rar_find_output *state,
const wchar_t * const file, /* NULL = give next */
size_t file_size, /* length + 1 */
int directory_match);
/* end entry search API }}} */
/* rararch.c */
int _rar_create_rararch_obj(const char* resolved_path,
const char* open_password,
zval *volume_callback, /* must be callable or NULL */
zval *object,
int *err_code TSRMLS_DC);
void _rar_close_file_resource(rar_file_t *rar);
/* Fetches the rar_file_t part of the RarArchive object in order to use the
* operations above and (discouraged) to have direct access to the fields
* RarEntry::extract/getStream access extract_open_dat and cb_userdata */
int _rar_get_file_resource_zv(zval *zv_file, rar_file_t **rar_file TSRMLS_DC);
int _rar_get_file_resource_zv_ex(zval *zv_file, rar_file_t **rar_file, int silent TSRMLS_DC);
int _rar_get_file_resource_ex(rar_obj_ref objref_file, rar_file_t **rar_file, int silent TSRMLS_DC);
void minit_rararch(TSRMLS_D);
PHP_FUNCTION(rar_open);
PHP_FUNCTION(rar_list);
PHP_FUNCTION(rar_entry_get);
PHP_FUNCTION(rar_solid_is);
PHP_FUNCTION(rar_comment_get);
PHP_FUNCTION(rar_broken_is);
PHP_FUNCTION(rar_allow_broken_set);
PHP_FUNCTION(rar_close);
PHP_METHOD(rarentry, extract);
PHP_METHOD(rarentry, getName);
PHP_METHOD(rarentry, getUnpackedSize);
PHP_METHOD(rarentry, getPackedSize);
PHP_METHOD(rarentry, getHostOs);
PHP_METHOD(rarentry, getFileTime);
PHP_METHOD(rarentry, getCrc);
PHP_METHOD(rarentry, getAttr);
PHP_METHOD(rarentry, getVersion);
PHP_METHOD(rarentry, getMethod);
/* rarentry.c */
extern zend_class_entry *rar_class_entry_ptr;
void minit_rarentry(TSRMLS_D);
void _rar_entry_to_zval(zval *parent,
struct RARHeaderDataEx *entry,
zend_ulong packed_size,
size_t index,
zval *entry_object TSRMLS_DC);
typedef struct rar {
int id;
int entry_count;
struct RARHeaderData **entries;
struct RAROpenArchiveData *list_handle;
struct RAROpenArchiveData *extract_handle;
void *list_data;
char *password;
} rar_file_t;
/* rar_stream.c */
php_stream *php_stream_rar_open(char *arc_name,
size_t position,
rar_cb_user_data *cb_udata_ptr /* will be copied */
STREAMS_DC TSRMLS_DC);
extern php_stream_wrapper php_stream_rar_wrapper;
/* rar_time.c */
void rar_time_convert(unsigned low, unsigned high, time_t *to);
int rar_dos_time_convert(unsigned dos_time, time_t *to);
#ifdef PHP_WIN32
#define timegm _mkgmtime
#endif
#endif /* PHP_RAR_H */

189
php_upgrade.md Normal file
View File

@@ -0,0 +1,189 @@
# PHP 8.18.5 Upgrade Procedure for php-rar
This document describes the step-by-step procedure to extend php-rar support
from PHP 8.0 to PHP 8.5. Each minor version is handled independently: CI is
wired up, the extension is compiled and tested inside the matching Docker image,
code changes are applied to fix any failures, and only then is the next version
tackled.
---
## Overview of files touched per version
| File | Change |
|---|---|
| `.github/docker-image-shas.yml` | Add new tag → SHA entries |
| `.github/scripts/update-docker-shas.sh` | Add new tags to the `TAGS` array |
| `Justfile` | Add image variables and `test-X_Y-*` targets |
| `*.c` / `*.h` | C source changes for API compatibility |
| `.github/workflows/tests.yml` | Windows job — update `php-version` (once per bump) |
The Linux CI matrix is generated automatically from `docker-image-shas.yml`, so
no manual edit to `tests.yml` is needed for Linux jobs.
---
## Repeatable procedure for each version
Follow these numbered steps for **each** minor version in order. Example:
8.0 → 8.1 → 8.2 → 8.3 → 8.4 → 8.5.
### Step 1 — Read the upgrade guides in php-src
Clone or browse php-src on the target branch, e.g. `PHP-8.1`:
```
https://github.com/php/php-src/blob/PHP-8.X/UPGRADING
https://github.com/php/php-src/blob/PHP-8.X/UPGRADING.INTERNALS
```
Focus on sections relevant to C extensions:
- Removed or renamed macros / functions
- Changed return types (`int``zend_result`)
- Changed struct member types
- New mandatory includes
- Any other backwards-incompatible changes
The per-version notes below summarise the items relevant to php-rar.
### Step 2 — Add the Docker image SHA
Fetch the OCI index digest from Docker Hub for the two new tags:
```bash
# Quick one-liner — prints the index digest for a given tag
curl -fsSL "https://hub.docker.com/v2/repositories/datadog/dd-appsec-php-ci/tags/php-X.Y-debug" \
| python3 -c "import sys,json; print(json.load(sys.stdin)['digest'])"
```
Or regenerate everything at once with the provided script after adding the new
tags to it (see Step 3):
```bash
.github/scripts/update-docker-shas.sh
```
Append the two lines to `.github/docker-image-shas.yml`:
```yaml
php-X.Y-debug: "sha256:<INDEX-DIGEST>"
php-X.Y-release-zts: "sha256:<INDEX-DIGEST>"
```
Also add both tags to the `TAGS` array in `.github/scripts/update-docker-shas.sh`:
```bash
TAGS=(
...existing tags...
php-X.Y-debug php-X.Y-release-zts
)
```
### Step 3 — Add Justfile targets
Add image variables and `test-X_Y-*` targets following the existing pattern:
```just
image_X_Y_debug := _base + `grep 'php-X.Y-debug:' .github/docker-image-shas.yml | cut -d'"' -f2`
image_X_Y_release_zts := _base + `grep 'php-X.Y-release-zts:' .github/docker-image-shas.yml | cut -d'"' -f2`
test-X_Y-debug:
{{_run}} {{image_X_Y_debug}} .github/scripts/build-and-test.sh
test-X_Y-release-zts:
{{_run}} {{image_X_Y_release_zts}} .github/scripts/build-and-test.sh
test-X_Y: test-X_Y-debug test-X_Y-release-zts
```
Add `test-X_Y` to the `test-linux` aggregate at the bottom.
### Step 4 — Compile and test
Run both variants locally before pushing:
```bash
just test-X_Y-debug
just test-X_Y-release-zts
```
Or both together:
```bash
just test-X_Y
```
Examine the output for compiler warnings, errors, and test failures.
### Step 5 — Apply C source changes
Based on the compilation output and the per-version notes below, make the
minimum necessary changes to `.c`/`.h` files. Guard every change with `#if
PHP_VERSION_ID >= XXYY00` so that older PHP versions continue to work.
### Step 6 — Re-run tests until green
Repeat Step 4 after each change. When both `debug` and `release-zts` pass,
commit.
### Step 7 — Push and verify CI
Push the branch. The `linux` CI job matrix is auto-built from
`docker-image-shas.yml` — the new versions appear automatically. Verify the
GitHub Actions run is green for all new jobs.
### Step 8 — Update Windows CI (optional, once per bump)
The Windows job in `.github/workflows/tests.yml` pins a specific PHP version.
Update it when the Linux jobs for the matching version are confirmed green:
```yaml
- name: Build and test
uses: php/php-windows-builder/extension@v1
with:
php-version: 'X.Y' # ← change here
```
Also update the `name:` and artifact `name:` strings in the same Windows job
block.
---
## Current Docker image SHAs (as of 2026-03-01)
These are the OCI index digests (multi-arch: amd64 + arm64) to use in
`docker-image-shas.yml`.
```yaml
php-8.1-debug: "sha256:1a1e5b44cf043e59768c65fd7c94aaefdacde5fa96d83102d35db11ad86f24c6"
php-8.1-release-zts: "sha256:5b8a269b4228d9191420059daef820b660110be0aca6776557924172fd1ff0c8"
php-8.2-debug: "sha256:52ad14560672fc8c5130f5758bbee3fa401bc1d35b412f4a230c6258143291a5"
php-8.2-release-zts: "sha256:cb143d915b394f16a2d78018765705460f3d1b788fdd2a90ef50fad5f8f5918c"
php-8.3-debug: "sha256:bb6df08160126374d3d9247428928aa19a9c2b2429c98356650199b85ae20212"
php-8.3-release-zts: "sha256:e58e25a017f75df82691d408b8cb70453875ff36718e295ee8c6653a0f117331"
php-8.4-debug: "sha256:15045688f6986f4625b1507a7f4be6104e7bbb88caf877f1611463b929f2bca2"
php-8.4-release-zts: "sha256:8e0ac25a3306b4b9f692c593b8a509cc789c2e001ce52682928065a92c880136"
php-8.5-debug: "sha256:bd0170331b34fb469e29d00b19b20fb88b726160f76df274a1bdc3a27ac18d30"
php-8.5-release-zts: "sha256:e071b2095da55bd24686209422f43a01c65acfc6021f04156d9fb43fd3d4d426"
```
Refresh at any time with `.github/scripts/update-docker-shas.sh` after adding
the new tags.
---
## Summary checklist
For each version X.Y in order (8.1, 8.2, 8.3, 8.4, 8.5):
- [ ] Read `PHP-X.Y/UPGRADING.INTERNALS` on GitHub
- [ ] Add two SHA entries to `.github/docker-image-shas.yml`
- [ ] Add both tags to `TAGS` array in `.github/scripts/update-docker-shas.sh`
- [ ] Add `image_X_Y_*` variables and `test-X_Y-*` targets to `Justfile`
- [ ] Add `test-X_Y` to `test-linux` aggregate in `Justfile`
- [ ] Run `just test-X_Y` and fix all compilation errors
- [ ] Run `just test-X_Y` again; confirm all tests pass
- [ ] Commit infrastructure + code changes together
- [ ] Push; confirm GitHub Actions CI is green for the new matrix entries
- [ ] (Optional) Update Windows `php-version` in `.github/workflows/tests.yml` to X.Y
<!-- vim: set tw=80: -->

774
rar.c Normal file
View File

@@ -0,0 +1,774 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2009 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
| |
| **** WARNING **** |
| |
| This module makes use of unRAR - free utility for RAR archives. |
| Its license states that you MUST NOT use its code to develop |
| a RAR (WinRAR) compatible archiver. |
| Please, read unRAR license for full information. |
| unRAR & RAR copyrights are owned by Eugene Roshal |
+----------------------------------------------------------------------+
| Author: Antony Dovgal <tony@daylessday.org> |
| Author: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <string.h>
#ifdef PHP_WIN32
# include <math.h>
#endif
#include <wchar.h>
#include <php.h>
#include <php_ini.h>
#include <zend_exceptions.h>
#include <ext/standard/info.h>
#include <ext/spl/spl_exceptions.h>
#include "unrar/rardefs.hpp"
#include "php_rar.h"
/* {{{ Function prototypes for functions with internal linkage */
static void _rar_fix_wide(wchar_t *str, size_t max_size);
static int _rar_unrar_volume_user_callback(char* dst_buffer,
zend_fcall_info *fci,
zend_fcall_info_cache *cache
TSRMLS_DC);
static int _rar_make_userdata_fcall(zval *callable,
zend_fcall_info *fci,
zend_fcall_info_cache *cache TSRMLS_DC);
/* }}} */
/* {{{ Functions with external linkage */
#if !defined(HAVE_STRNLEN) || !HAVE_STRNLEN
size_t _rar_strnlen(const char *s, size_t maxlen) /* {{{ */
{
char *r = memchr(s, '\0', maxlen);
return r ? r-s : maxlen;
}
/* }}} */
#endif
/* From unicode.cpp
* I can't use that one directy because it takes a const wchar, not wchar_t.
* And I shouldn't because it's not a public API.
*/
void _rar_wide_to_utf(const wchar_t *src, char *dest, size_t dest_size) /* {{{ */
{
long dsize= (long) dest_size;
dsize--;
while (*src != 0 && --dsize >= 0) {
uint c =*(src++);
if (c < 0x80)
*(dest++) = (char) c;
else if (c < 0x800 && --dsize >= 0) {
*(dest++) = (char) (0xc0 | (c >> 6));
*(dest++) = (0x80 | (c & 0x3f));
}
else if (c < 0x10000 && (dsize -= 2) >= 0) {
*(dest++) = (char) (0xe0 | (c >> 12));
*(dest++) = (0x80 | ((c >> 6) & 0x3f));
*(dest++) = (0x80 | (c & 0x3f));
}
else if (c < 0x200000 && (dsize -= 3) >= 0) {
*(dest++) = (char) (0xf0 | (c >> 18));
*(dest++) = (0x80 | ((c >> 12) & 0x3f));
*(dest++) = (0x80 | ((c >> 6) & 0x3f));
*(dest++) = (0x80 | (c & 0x3f));
}
}
*dest = 0;
}
/* }}} */
/* idem */
void _rar_utf_to_wide(const char *src, wchar_t *dest, size_t dest_size) /* {{{ */
{
long dsize = (long) dest_size;
dsize--;
while (*src != 0) {
uint c = (unsigned char) *(src++),
d;
if (c < 0x80)
d = c;
else if ((c >> 5) == 6) {
if ((*src & 0xc0) != 0x80)
break;
d=((c & 0x1f) << 6)|(*src & 0x3f);
src++;
}
else if ((c>>4)==14) {
if ((src[0] & 0xc0) != 0x80 || (src[1] & 0xc0) != 0x80)
break;
d = ((c & 0xf) << 12) | ((src[0] & 0x3f) << 6) | (src[1] & 0x3f);
src += 2;
}
else if ((c>>3)==30) {
if ((src[0] & 0xc0) != 0x80 || (src[1] & 0xc0) != 0x80 || (src[2] & 0xc0) != 0x80)
break;
d = ((c & 7) << 18) | ((src[0] & 0x3f) << 12) | ((src[1] & 0x3f) << 6) | (src[2] & 0x3f);
src += 3;
}
else
break;
if (--dsize < 0)
break;
if (d > 0xffff) {
if (--dsize < 0 || d > 0x10ffff)
break;
*(dest++) = (wchar_t) (((d - 0x10000) >> 10) + 0xd800);
*(dest++) = (d & 0x3ff) + 0xdc00;
}
else
*(dest++) = (wchar_t) d;
}
*dest = 0;
}
/* }}} */
void _rar_destroy_userdata(rar_cb_user_data *udata) /* {{{ */
{
assert(udata != NULL);
if (udata->password != NULL) {
efree(udata->password);
}
if (udata->callable != NULL) {
zval_ptr_dtor(udata->callable);
efree(udata->callable);
}
udata->password = NULL;
udata->callable = NULL;
}
/* }}} */
int _rar_find_file(struct RAROpenArchiveDataEx *open_data, /* IN */
const char *const utf_file_name, /* IN */
rar_cb_user_data *cb_udata, /* IN, must be managed outside */
void **arc_handle, /* OUT: where to store rar archive handle */
int *found, /* OUT */
struct RARHeaderDataEx *header_data /* OUT, can be null */
) /* {{{ */
{
wchar_t *file_name = NULL;
size_t utf_file_name_len = strlen(utf_file_name);
int ret;
file_name = ecalloc(utf_file_name_len + 1, sizeof *file_name);
_rar_utf_to_wide(utf_file_name, file_name, utf_file_name_len + 1);
ret = _rar_find_file_w(open_data, file_name, cb_udata, arc_handle, found,
header_data);
efree(file_name);
return ret;
}
/* }}} */
/* WARNING: It's the caller who must close the archive and manage the lifecycle
of cb_udata (must be valid while the archive is opened). */
/*
* This function opens a RAR file and looks for the file with the
* name utf_file_name.
* If the operation is sucessful, arc_handle is populated with the RAR file
* handle, found is set to TRUE if the file is found and FALSE if it is not
* found; additionaly, the optional header_data is populated with the first
* header that corresponds to the request file. If the file is not found and
* header_data is specified, its values are undefined.
* Note that even when the file is not found, the caller must still close
* the archive.
*/
int _rar_find_file_w(struct RAROpenArchiveDataEx *open_data, /* IN */
const wchar_t *const file_name, /* IN */
rar_cb_user_data *cb_udata, /* IN, must be managed outside */
void **arc_handle, /* OUT: where to store rar archive handle */
int *found, /* OUT */
struct RARHeaderDataEx *header_data /* OUT, can be null */
) /* {{{ */
{
int result,
process_result;
struct RARHeaderDataEx *used_header_data;
int retval = 0; /* success in rar parlance */
assert(open_data != NULL);
assert(file_name != NULL);
assert(arc_handle != NULL);
assert(found != NULL);
*found = FALSE;
*arc_handle = NULL;
used_header_data = header_data != NULL ?
header_data :
ecalloc(1, sizeof *used_header_data);
*arc_handle = RAROpenArchiveEx(open_data);
if (*arc_handle == NULL) {
retval = open_data->OpenResult;
goto cleanup;
}
RARSetCallback(*arc_handle, _rar_unrar_callback, (LPARAM) cb_udata);
while ((result = RARReadHeaderEx(*arc_handle, used_header_data)) == 0) {
#if WCHAR_MAX > 0xffff
_rar_fix_wide(used_header_data->FileNameW,
ARR_SIZE(used_header_data->FileNameW));
#endif
if (wcsncmp(used_header_data->FileNameW, file_name,
ARR_SIZE(used_header_data->FileNameW)) == 0) {
*found = TRUE;
goto cleanup;
}
else {
process_result = RARProcessFile(*arc_handle, RAR_SKIP, NULL, NULL);
}
if (process_result != 0) {
retval = process_result;
goto cleanup;
}
}
if (result != 0 && result != 1) {
/* 0 indicates success, 1 indicates normal end of file */
retval = result;
goto cleanup;
}
cleanup:
if (header_data == NULL)
efree(used_header_data);
return retval;
}
/* }}} */
int _rar_find_file_p(struct RAROpenArchiveDataEx *open_data, /* IN */
size_t position, /* IN */
rar_cb_user_data *cb_udata, /* IN, must be managed outside */
void **arc_handle, /* OUT: where to store rar archive handle */
int *found, /* OUT */
struct RARHeaderDataEx *header_data /* OUT, can be null */
) /* {{{ */
{
int result,
process_result;
struct RARHeaderDataEx *used_header_data;
int retval = 0; /* success in rar parlance */
size_t curpos = 0;
assert(open_data != NULL);
assert(arc_handle != NULL);
assert(found != NULL);
*found = FALSE;
*arc_handle = NULL;
used_header_data = header_data != NULL ?
header_data :
ecalloc(1, sizeof *used_header_data);
*arc_handle = RAROpenArchiveEx(open_data);
if (*arc_handle == NULL) {
retval = open_data->OpenResult;
goto cleanup;
}
RARSetCallback(*arc_handle, _rar_unrar_callback, (LPARAM) cb_udata);
while ((result = RARReadHeaderEx(*arc_handle, used_header_data)) == 0) {
/* skip entries that were split before with incrementing current pos */
if ((used_header_data->Flags & RHDF_SPLITBEFORE) ||
(curpos++ != position)) {
process_result = RARProcessFile(*arc_handle, RAR_SKIP, NULL, NULL);
} else {
*found = TRUE;
goto cleanup;
}
if (process_result != 0) {
retval = process_result;
goto cleanup;
}
}
if (result != 0 && result != 1) {
/* 0 indicates success, 1 indicates normal end of file */
retval = result;
goto cleanup;
}
cleanup:
if (header_data == NULL)
efree(used_header_data);
return retval;
}
/* An unRAR callback.
* Processes requests for passwords and missing volumes
* If there is (userland) volume find callback specified, try to use that
* callback to retrieve the name of the missing volume. Otherwise, or if
* the volume find callback returns null, cancel the operation. */
int CALLBACK _rar_unrar_callback(UINT msg, LPARAM UserData, LPARAM P1, LPARAM P2) /* {{{ */
{
rar_cb_user_data *userdata = (rar_cb_user_data*) UserData;
TSRMLS_FETCH();
if (msg == UCM_NEEDPASSWORD) {
/* user data is the password or null if none */
char *password = userdata->password;
if (password == NULL || password[0] == '\0') {
/*php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Password needed, but it has not been specified");*/
return -1;
}
else {
strncpy((char *) P1, password, (size_t) P2);
assert((size_t) P2 > 0);
((char *) P1)[(size_t) P2 - 1] = '\0';
}
}
else if (msg == UCM_CHANGEVOLUME) {
if (((int) P2) == RAR_VOL_ASK) {
int ret, called_cb = 0;
if (userdata->callable == NULL) {
/* if there's no callback, abort */
ret = -1;
}
else {
zend_fcall_info fci;
zend_fcall_info_cache cache;
/* make_userdata_fcall and volume_user_callback are chatty */
if (_rar_make_userdata_fcall(userdata->callable, &fci, &cache
TSRMLS_CC) == SUCCESS) {
ret = _rar_unrar_volume_user_callback(
(char*) P1, &fci, &cache TSRMLS_CC);
called_cb = 1;
}
else {
ret = -1;
}
}
/* always a warning, never an exception here */
if (ret == -1 && !called_cb)
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Volume %s was not found", (char*) P1);
return ret;
}
}
// TODO: maybe support UCM_NEEDPASSWORDW and UCM_CHANGEVOLUMEW
return 0;
}
/* }}} */
PHP_FUNCTION(rar_bogus_ctor) /* {{{ */
{
/* This exception should not be thrown. The point is to add this as
* a class constructor and make it private. This code would be able to
* run only if the constructor were made public */
zend_throw_exception(NULL,
"An object of this type cannot be created with the new operator.",
0 TSRMLS_CC);
}
/* }}} */
PHP_FUNCTION(rar_wrapper_cache_stats) /* {{{ */
{
char *result = NULL;
int len;
if (zend_parse_parameters_none() == FAILURE)
return;
len = spprintf(&result, 0, "%u/%u (hits/misses)",
RAR_G(contents_cache).hits, RAR_G(contents_cache).misses);
RAR_RETURN_STRINGL(result, len, 0);
}
/* }}} */
/* }}} */
/* {{{ Functions with internal linkage */
/*
* Only relevant when sizeof(wchar_t) > 2 (so not windows).
* Removes the characters use value if > 0x10ffff; these are not
* valid UTF characters.
*/
static void _rar_fix_wide(wchar_t *str, size_t max_size) /* {{{ */
{
wchar_t *write,
*read,
*max_fin;
max_fin = str + max_size;
for (write = str, read = str; *read != L'\0' && read != max_fin; read++) {
if ((unsigned) *read <= 0x10ffff)
*(write++) = *read;
}
*write = L'\0';
}
/* }}} */
/* called from the RAR callback; calls a user callback in case a volume was
* not found
* This function sends messages instead of calling _rar_handle_ext_error
* because, in case we're using exceptions, we want to let an exception with
* error code ERAR_EOPEN to be thrown.
*/
static int _rar_unrar_volume_user_callback(char* dst_buffer, // MAXPATHSIZE
zend_fcall_info *fci,
zend_fcall_info_cache *cache
TSRMLS_DC) /* {{{ */
{
zval failed_vol,
retval,
*params,
*const retval_ptr = &retval;
int ret = -1;
ZVAL_STRING(&failed_vol, dst_buffer);
ZVAL_NULL(&retval);
params = &failed_vol;
fci->retval = &retval;
fci->params = params;
fci->param_count = 1;
if (zend_call_function(fci, cache TSRMLS_CC) != SUCCESS || EG(exception)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Failure to call volume find callback");
goto cleanup;
}
assert(fci->retval == &retval);
if (Z_TYPE_P(retval_ptr) == IS_NULL) {
/* let return -1 */
}
else if (Z_TYPE_P(retval_ptr) == IS_STRING) {
char *filename = Z_STRVAL_P(retval_ptr);
char resolved_path[MAXPATHSIZE];
size_t resolved_len;
if (OPENBASEDIR_CHECKPATH(filename)) {
goto cleanup;
}
if (!expand_filepath(filename, resolved_path TSRMLS_CC)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Cound not expand filename %s", filename);
goto cleanup;
}
resolved_len = _rar_strnlen(resolved_path, MAXPATHSIZE);
if (resolved_len > MAXPATHSIZE - 1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Resolved path is too big for the unRAR library");
goto cleanup;
}
strncpy(dst_buffer, resolved_path, MAXPATHSIZE);
dst_buffer[MAXPATHSIZE - 1] = '\0';
ret = 1; /* try this new filename */
}
else {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Wrong type returned by volume find callback, "
"expected string or NULL");
/* let return -1 */
}
cleanup:
zval_ptr_dtor(&failed_vol);
zval_ptr_dtor(&retval);
return ret;
}
/* }}} */
static int _rar_make_userdata_fcall(zval *callable,
zend_fcall_info *fci,
zend_fcall_info_cache *cache TSRMLS_DC) /* {{{ */
{
char *error = NULL;
assert(callable != NULL);
assert(fci != NULL);
assert(cache != NULL);
*cache = empty_fcall_info_cache;
if (zend_fcall_info_init(callable, IS_CALLABLE_STRICT, fci, cache, NULL,
&error TSRMLS_CC) == SUCCESS) {
if (error) {
php_error_docref(NULL TSRMLS_CC, E_STRICT,
"The RAR file was not opened with a strictly valid callback (%s)",
error);
efree(error);
}
return SUCCESS;
}
else {
if (error) {
php_error_docref(NULL TSRMLS_CC, E_STRICT,
"The RAR file was not opened with a valid callback (%s)",
error);
efree(error);
}
return FAILURE;
}
}
/* }}} */
/* }}} */
#ifdef COMPILE_DL_RAR
ZEND_GET_MODULE(rar)
#endif
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO_EX(arginfo_rar_open, 0, 0, 1)
ZEND_ARG_INFO(0, filename)
ZEND_ARG_INFO(0, password)
ZEND_ARG_INFO(0, volume_callback)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_rar_void_archmeth, 0, 0, 1)
#if 0 /* don't turn on type hinting yet */
ZEND_ARG_OBJ_INFO(0, rarfile, RarArchive, 0)
#else
ZEND_ARG_INFO(0, rarfile)
#endif
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_rar_entry_get, 0, 0, 2)
#if 0 /* don't turn on type hinting yet */
ZEND_ARG_OBJ_INFO(0, rarfile, RarArchive, 0)
#else
ZEND_ARG_INFO(0, rarfile)
#endif
ZEND_ARG_INFO(0, filename)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_rar_allow_broken_set, 0, 0, 2)
#if 0 /* don't turn on type hinting yet */
ZEND_ARG_OBJ_INFO(0, rarfile, RarArchive, 0)
#else
ZEND_ARG_INFO(0, rarfile)
#endif
ZEND_ARG_INFO(0, allow_broken)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_rar_wrapper_cache_stats, 0)
ZEND_END_ARG_INFO()
/* }}} */
/* {{{ rar_functions[]
*
*/
/* clang-format off */
static zend_function_entry rar_functions[] = {
PHP_FE(rar_open, arginfo_rar_open)
PHP_FE(rar_list, arginfo_rar_void_archmeth)
PHP_FE(rar_entry_get, arginfo_rar_entry_get)
PHP_FE(rar_solid_is, arginfo_rar_void_archmeth)
PHP_FE(rar_comment_get, arginfo_rar_void_archmeth)
PHP_FE(rar_broken_is, arginfo_rar_void_archmeth)
PHP_FE(rar_allow_broken_set, arginfo_rar_allow_broken_set)
PHP_FE(rar_close, arginfo_rar_void_archmeth)
PHP_FE(rar_wrapper_cache_stats, arginfo_rar_wrapper_cache_stats)
{NULL, NULL, NULL}
};
/* clang-format on */
/* }}} */
/* {{{ Globals' related activities */
ZEND_DECLARE_MODULE_GLOBALS(rar);
static int _rar_array_apply_remove_first(zval *pDest TSRMLS_DC)
{
return (ZEND_HASH_APPLY_STOP | ZEND_HASH_APPLY_REMOVE);
}
static void _rar_contents_cache_put(const char *key,
uint key_len,
zval *zv TSRMLS_DC)
{
rar_contents_cache *cc = &RAR_G(contents_cache);
int cur_size;
cur_size = zend_hash_num_elements(cc->data);
if (cur_size == cc->max_size) {
zend_hash_apply(cc->data, _rar_array_apply_remove_first TSRMLS_CC);
assert(zend_hash_num_elements(cc->data) == cur_size - 1);
}
rar_zval_add_ref(&zv);
zend_hash_str_update(cc->data, key, key_len, zv);
}
static zval *_rar_contents_cache_get(const char *key,
uint key_len,
zval *rv TSRMLS_DC)
{
rar_contents_cache *cc = &RAR_G(contents_cache);
zval *element = NULL;
element = zend_hash_str_find(cc->data, key, key_len);
if (element != NULL) {
cc->hits++;
INIT_ZVAL(*rv);
ZVAL_COPY_VALUE(rv, element);
zval_copy_ctor(rv);
return rv;
}
else {
cc->misses++;
return NULL;
}
}
/* ZEND_MODULE_GLOBALS_CTOR_D declares it receiving zend_rar_globals*,
* which is incompatible; once cast into ts_allocate_ctor by the macro,
* ZEND_INIT_MODULE_GLOBALS, it cannot (per the spec) be used. */
static void ZEND_MODULE_GLOBALS_CTOR_N(rar)(void *arg TSRMLS_DC) /* {{{ */
{
zend_rar_globals *rar_globals = arg;
rar_globals->contents_cache.max_size = 5; /* TODO make configurable */
rar_globals->contents_cache.hits = 0;
rar_globals->contents_cache.misses = 0;
rar_globals->contents_cache.put = _rar_contents_cache_put;
rar_globals->contents_cache.get = _rar_contents_cache_get;
rar_globals->contents_cache.data =
pemalloc(sizeof *rar_globals->contents_cache.data, 1);
zend_hash_init(rar_globals->contents_cache.data,
rar_globals->contents_cache.max_size, NULL,
ZVAL_PTR_DTOR, 1);
}
/* }}} */
static void ZEND_MODULE_GLOBALS_DTOR_N(rar)(void *arg TSRMLS_DC) /* {{{ */
{
zend_rar_globals *rar_globals = arg;
zend_hash_destroy(rar_globals->contents_cache.data);
pefree(rar_globals->contents_cache.data, 1);
}
/* }}} */
/* }}} */
/* {{{ ZEND_MODULE_STARTUP */
ZEND_MODULE_STARTUP_D(rar)
{
minit_rararch(TSRMLS_C);
minit_rarentry(TSRMLS_C);
minit_rarerror(TSRMLS_C);
/* This doesn't work, it tries to call the destructor after the
* module has been unloaded. This information is in the zend_module_entry
* instead; that information is correctly used before the module is
* unloaded */
/* ZEND_INIT_MODULE_GLOBALS(rar, ZEND_MODULE_GLOBALS_CTOR_N(rar),
ZEND_MODULE_GLOBALS_DTOR_N(rar)); */
php_register_url_stream_wrapper("rar", &php_stream_rar_wrapper TSRMLS_CC);
/* clang-format off */
REGISTER_LONG_CONSTANT("RAR_HOST_MSDOS", HOST_MSDOS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_OS2", HOST_OS2, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_WIN32", HOST_WIN32, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_UNIX", HOST_UNIX, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_MACOS", HOST_MACOS, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("RAR_HOST_BEOS", HOST_BEOS, CONST_CS | CONST_PERSISTENT);
/* clang-format on */
return SUCCESS;
}
/* }}} */
/* {{{ ZEND_MODULE_DEACTIVATE */
ZEND_MODULE_DEACTIVATE_D(rar)
{
/* clean cache on request shutdown */
zend_hash_clean(RAR_G(contents_cache).data);
return SUCCESS;
}
/* }}} */
/* {{{ ZEND_MODULE_INFO */
ZEND_MODULE_INFO_D(rar)
{
char version[256];
char api_version[256];
php_info_print_table_start();
php_info_print_table_header(2, "RAR support", "enabled");
php_info_print_table_row(2, "RAR EXT version", PHP_RAR_VERSION);
#if RARVER_BETA != 0
sprintf(version,"%d.%02d beta%d patch%d %d-%02d-%02d", RARVER_MAJOR,
RARVER_MINOR, RARVER_BETA, RARVER_PATCH, RARVER_YEAR, RARVER_MONTH,
RARVER_DAY);
#else
sprintf(version,"%d.%02d patch%d %d-%02d-%02d", RARVER_MAJOR, RARVER_MINOR,
RARVER_PATCH, RARVER_YEAR, RARVER_MONTH, RARVER_DAY);
#endif
sprintf(api_version,"%d extension %d", RAR_DLL_VERSION,
RAR_DLL_EXT_VERSION);
php_info_print_table_row(2, "UnRAR version", version);
php_info_print_table_row(2, "UnRAR API version", api_version);
php_info_print_table_end();
}
/* }}} */
/* {{{ rar_module_entry
*/
zend_module_entry rar_module_entry = {
STANDARD_MODULE_HEADER,
"rar",
rar_functions,
ZEND_MODULE_STARTUP_N(rar),
/* ZEND_MODULE_SHUTDOWN_N(rar), */
NULL,
/* ZEND_MODULE_ACTIVATE_N(rar), */
NULL,
ZEND_MODULE_DEACTIVATE_N(rar),
ZEND_MODULE_INFO_N(rar),
PHP_RAR_VERSION,
ZEND_MODULE_GLOBALS(rar),
ZEND_MODULE_GLOBALS_CTOR_N(rar),
ZEND_MODULE_GLOBALS_DTOR_N(rar),
NULL, /* post_deactivate_func */
STANDARD_MODULE_PROPERTIES_EX,
};
/* }}} */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/

722
rar.cpp
View File

@@ -1,722 +0,0 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2004 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
| |
| **** WARNING **** |
| |
| This module makes use of unRAR - free utility for RAR archives. |
| It's license states, that you MUST NOT use it's code to develop |
| a RAR (WinRAR) compatible archiver. |
| Please, read unRAR license for full information. |
| unRAR & RAR copyrights are owned by Eugene Roshal |
+----------------------------------------------------------------------+
| Author: Antony Dovgal <tony2001@phpclub.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
extern "C" {
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
}
#if HAVE_RAR
extern "C" {
#include "php_rar.h"
}
#include "unrar/rar.hpp"
static int le_rar_file;
#define le_rar_file_name "Rar"
static zend_class_entry *rar_class_entry_ptr;
/* {{{ rar_functions[]
*
*/
function_entry rar_functions[] = {
PHP_FE(rar_open, NULL)
PHP_FE(rar_list, NULL)
PHP_FE(rar_entry_get, NULL)
PHP_FE(rar_close, NULL)
{NULL, NULL, NULL}
};
static zend_function_entry php_rar_class_functions[] = {
PHP_ME(rarentry, extract, NULL, 0)
PHP_ME(rarentry, getName, NULL, 0)
PHP_ME(rarentry, getUnpackedSize, NULL, 0)
PHP_ME(rarentry, getPackedSize, NULL, 0)
PHP_ME(rarentry, getHostOs, NULL, 0)
PHP_ME(rarentry, getFileTime, NULL, 0)
PHP_ME(rarentry, getCrc, NULL, 0)
PHP_ME(rarentry, getAttr, NULL, 0)
PHP_ME(rarentry, getVersion, NULL, 0)
PHP_ME(rarentry, getMethod, NULL, 0)
{NULL, NULL, NULL}
};
/* }}} */
/* {{{ rar_module_entry
*/
zend_module_entry rar_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"rar",
rar_functions,
PHP_MINIT(rar),
PHP_MSHUTDOWN(rar),
PHP_RINIT(rar), /* Replace with NULL if there's nothing to do at request start */
PHP_RSHUTDOWN(rar), /* Replace with NULL if there's nothing to do at request end */
PHP_MINFO(rar),
#if ZEND_MODULE_API_NO >= 20010901
"0.1", /* Replace with version number for your extension */
#endif
STANDARD_MODULE_PROPERTIES
};
/* }}} */
/* {{{ internal functions protos */
static void _rar_file_list_dtor(zend_rsrc_list_entry * TSRMLS_DC);
static int _rar_list_files(rar_file_t * TSRMLS_DC);
static int _rar_handle_error(int TSRMLS_DC);
static void _rar_dos_date_to_text(int, char *);
static void _rar_entry_to_zval(struct RARHeaderData *, zval * TSRMLS_DC);
static zval **_rar_entry_get_property(zval *, char *, int TSRMLS_DC);
/* }}} */
/* <internal> */
static void _rar_file_list_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
{
rar_file_t *rar = (rar_file_t *)rsrc->ptr;
int i = 0;
if (rar->list_data) {
RARCloseArchive(rar->list_data);
}
if (rar->password) {
efree(rar->password);
}
if (rar->entries && rar->entry_count) {
for(i = 0; i < rar->entry_count; i++) {
efree(rar->entries[i]);
}
efree(rar->entries);
rar->entry_count = 0;
}
efree(rar->list_handle->ArcName);
efree(rar->list_handle);
efree(rar->extract_handle->ArcName);
efree(rar->extract_handle);
efree(rar);
}
/* }}} */
static int _rar_get_file_resource(zval **zval_file, rar_file_t **rar_file TSRMLS_DC) /* {{{ */
{
*rar_file = (rar_file_t *) zend_fetch_resource(zval_file TSRMLS_CC, -1, le_rar_file_name, NULL, 1, le_rar_file);
if (*rar_file) {
return 1;
}
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot find Rar file resource");
return 0;
}
/* }}} */
static int _rar_list_files(rar_file_t *rar TSRMLS_DC) /* {{{ */
{
int result = 0;
while (result == 0) {
struct RARHeaderData entry;
result = RARReadHeader(rar->list_data, &entry);
RARProcessFile(rar->list_data, RAR_OM_LIST, NULL, NULL);
if (result == 0) {
rar->entries = (struct RARHeaderData **)erealloc(rar->entries, sizeof(struct RARHeaderData *) * (rar->entry_count + 1));
if (!rar->entries) {
return FAILURE;
}
rar->entries[rar->entry_count] = (struct RARHeaderData *)emalloc(sizeof(struct RARHeaderData));
memcpy(rar->entries[rar->entry_count], &entry, sizeof(struct RARHeaderData));
rar->entry_count++;
}
}
return result;
}
/* }}} */
static int _rar_handle_error(int errcode TSRMLS_DC) /* {{{ */
{
switch (errcode) {
case 0:
/* no error */
return SUCCESS;
break;
case ERAR_END_ARCHIVE:
/* no error */
return SUCCESS;
break;
case ERAR_NO_MEMORY:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_NO_MEMORY: not enough memory");
break;
case ERAR_BAD_DATA:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_BAD_DATA");
break;
case ERAR_BAD_ARCHIVE:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_BAD_ARCHIVE");
break;
case ERAR_UNKNOWN_FORMAT:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_UNKNOWN_FORMAT");
break;
case ERAR_EOPEN:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_EOPEN");
break;
case ERAR_ECREATE:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_ECREATE");
break;
case ERAR_ECLOSE:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_ECLOSE");
break;
case ERAR_EREAD:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_EREAD");
break;
case ERAR_EWRITE:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_EWRITE");
break;
case ERAR_SMALL_BUF:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_SMALL_BUF");
break;
case ERAR_UNKNOWN:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "ERAR_UNKNOWN: unknown RAR error");
break;
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown RAR error");
break;
}
return FAILURE;
}
/* }}} */
static void _rar_dos_date_to_text(int dos_time, char *date_string) /* {{{ */
{
int second, minute, hour, day, month, year;
/* following lines were taken from timefn.cpp */
second = (dos_time & 0x1f)*2;
minute = (dos_time>>5) & 0x3f;
hour = (dos_time>>11) & 0x1f;
day = (dos_time>>16) & 0x1f;
month = (dos_time>>21) & 0x0f;
year = (dos_time>>25)+1980;
sprintf(date_string, "%u-%02u-%02u %02u:%02u:%02u", year, month, day, hour, minute, second);
}
/* }}} */
static void _rar_entry_to_zval(struct RARHeaderData *entry, zval *object TSRMLS_DC) /* {{{ */
{
char tmp_s [MAX_LENGTH_OF_LONG + 1];
char time[50];
add_property_string(object, "name", entry->FileName, 1);
add_property_long(object, "unpacked_size", entry->UnpSize);
add_property_long(object, "packed_size", entry->PackSize);
add_property_long(object, "host_os", entry->HostOS);
_rar_dos_date_to_text(entry->FileTime, time);
add_property_string(object, "file_time", time, 1);
sprintf(tmp_s, "%lx", entry->FileCRC);
add_property_string(object, "crc", tmp_s, 1);
add_property_long(object, "attr", entry->FileAttr);
add_property_long(object, "version", entry->UnpVer);
add_property_long(object, "method", entry->Method);
}
/* }}} */
static zval **_rar_entry_get_property(zval *id, char *name, int namelen TSRMLS_DC) /* {{{ */
{
zval **tmp;
if (zend_hash_find(Z_OBJPROP_P(id), name, namelen, (void **)&tmp) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to find property %s", name);
return NULL;
}
return tmp;
}
/* }}} */
/* </internal> */
#ifdef COMPILE_DL_RAR
extern "C" {
ZEND_GET_MODULE(rar)
}
#endif
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(rar)
{
zend_class_entry rar_class_entry;
INIT_CLASS_ENTRY(rar_class_entry, "RarEntry", php_rar_class_functions);
rar_class_entry_ptr = zend_register_internal_class(&rar_class_entry TSRMLS_CC);
le_rar_file = zend_register_list_destructors_ex(_rar_file_list_dtor, NULL, le_rar_file_name, module_number);
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MSHUTDOWN_FUNCTION
*/
PHP_MSHUTDOWN_FUNCTION(rar)
{
return SUCCESS;
}
/* }}} */
/* {{{ PHP_RINIT_FUNCTION
*/
PHP_RINIT_FUNCTION(rar)
{
return SUCCESS;
}
/* }}} */
/* {{{ PHP_RSHUTDOWN_FUNCTION
*/
PHP_RSHUTDOWN_FUNCTION(rar)
{
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(rar)
{
php_info_print_table_start();
php_info_print_table_header(2, "Rar support", "enabled");
php_info_print_table_row(2, "Revision", "$Revision$");
php_info_print_table_end();
}
/* }}} */
/* module functions */
/* {{{ proto rar_open(string filename [, string password])
Open Rar archive and return resource */
PHP_FUNCTION(rar_open)
{
zval **filename, **password;
rar_file_t *rar = NULL;
struct RARHeaderData entry;
int ac = ZEND_NUM_ARGS(), result = 0;
if (ac < 1 || ac > 2 || zend_get_parameters_ex(ac, &filename, &password) == FAILURE) {
WRONG_PARAM_COUNT;
}
convert_to_string_ex(filename);
if (php_check_open_basedir(Z_STRVAL_PP(filename) TSRMLS_CC)) {
RETURN_FALSE;
}
rar = (rar_file_t *) emalloc(sizeof(rar_file_t));
rar->list_handle = (RAROpenArchiveData *) emalloc(sizeof(RAROpenArchiveData));
rar->list_handle->ArcName = estrndup(Z_STRVAL_PP(filename), Z_STRLEN_PP(filename));
rar->list_handle->OpenMode = RAR_OM_LIST;
rar->extract_handle = (RAROpenArchiveData *) emalloc(sizeof(RAROpenArchiveData));
rar->extract_handle->ArcName = estrndup(Z_STRVAL_PP(filename), Z_STRLEN_PP(filename));
rar->extract_handle->OpenMode = RAR_OM_EXTRACT;
rar->password = NULL;
rar->entries = NULL;
rar->entry_count = 0;
rar->list_data = RAROpenArchive(rar->list_handle);
if (rar->list_data != NULL && rar->list_handle->OpenResult == 0) {
if (ac == 2) {
rar->password = estrndup(Z_STRVAL_PP(password), Z_STRLEN_PP(password));
}
rar->id = zend_list_insert(rar,le_rar_file);
RETURN_RESOURCE(rar->id);
}
else {
efree(rar->list_handle->ArcName);
efree(rar->list_handle);
efree(rar->extract_handle->ArcName);
efree(rar->extract_handle);
efree(rar);
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto rar_list(resource rarfile)
Return entries from the rar archive */
PHP_FUNCTION(rar_list)
{
zval **file;
rar_file_t *rar = NULL;
int i = 0;
int ac = ZEND_NUM_ARGS(), result = 0;
if (ac < 1 || ac > 1 || zend_get_parameters_ex(ac, &file) == FAILURE) {
WRONG_PARAM_COUNT;
}
if (!_rar_get_file_resource(file,&rar)) {
RETURN_FALSE;
}
if (rar->entries == NULL) {
result = _rar_list_files(rar TSRMLS_CC);
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
}
array_init(return_value);
for (i = 0; i < rar->entry_count; i++) {
zval *tmp;
MAKE_STD_ZVAL(tmp);
object_init_ex(tmp, rar_class_entry_ptr);
add_property_resource(tmp, "rarfile", rar->id);
_rar_entry_to_zval(rar->entries[i], tmp TSRMLS_CC);
zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp, sizeof(zval*), NULL);
}
if (!return_value) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to list files from RAR archive");
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto rar_entry_get(resource rarfile, string filename)
Return entry from the rar archive */
PHP_FUNCTION(rar_entry_get)
{
zval **file, **filename;
rar_file_t *rar = NULL;
int result = 0, i = 0;
int ac = ZEND_NUM_ARGS();
if (ac < 2 || ac > 2 || zend_get_parameters_ex(ac, &file, &filename) == FAILURE) {
WRONG_PARAM_COUNT;
}
if (!_rar_get_file_resource(file,&rar)) {
RETURN_FALSE;
}
if (rar->entries == NULL) {
result = _rar_list_files(rar TSRMLS_CC);
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
}
for(i = 0; i < rar->entry_count; i++){
if (strcmp(rar->entries[i]->FileName, Z_STRVAL_PP(filename)) == 0) {
object_init_ex(return_value, rar_class_entry_ptr);
add_property_resource(return_value, "rarfile", rar->id);
_rar_entry_to_zval(rar->entries[i], return_value TSRMLS_CC);
break;
}
}
if (!return_value) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot find such file in RAR archive");
RETURN_FALSE;
}
}
/* }}} */
/* {{{ proto rar_close(resource rarfile)
Close Rar archive and free all resources */
PHP_FUNCTION(rar_close)
{
zval **file;
rar_file_t *rar = NULL;
int file_counter = 0;
int ac = ZEND_NUM_ARGS();
if (ac < 1 || ac > 1 || zend_get_parameters_ex(ac, &file) == FAILURE) {
WRONG_PARAM_COUNT;
}
if (!_rar_get_file_resource(file,&rar)) {
RETURN_FALSE;
}
zend_list_delete(rar->id);
RETURN_TRUE;
}
/* }}} */
/* {{{ proto RarEntry::extract(string path [, string filename ]);
Extract file from the archive */
PHP_METHOD(rarentry, extract)
{
zval **rarfile, **path, **filename, **tmp, **tmp_name;
rar_file_t *rar = NULL;
char filename_str[260];
char *path_str = NULL, *extract_to_file = NULL;
int ac = ZEND_NUM_ARGS(), resource_type = 0, result = 0, process_result = 0;
zval *entry_obj = getThis();
unsigned long data_len;
struct RARHeaderData entry;
void *extract_data;
if (ac < 1 || ac > 2 || zend_get_parameters_ex(ac, &path, &filename) == FAILURE ) {
WRONG_PARAM_COUNT;
}
if ((tmp = _rar_entry_get_property(entry_obj, "rarfile", sizeof("rarfile") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
rar = (rar_file_t *) zend_list_find(Z_LVAL_PP(tmp), &resource_type);
convert_to_string_ex(path);
path_str = Z_STRVAL_PP(path);
if (php_check_open_basedir(Z_STRVAL_PP(path) TSRMLS_CC)) {
RETURN_FALSE;
}
if (ac == 2) {
convert_to_string_ex(filename);
extract_to_file = Z_STRVAL_PP(filename);
if (php_check_open_basedir(Z_STRVAL_PP(filename) TSRMLS_CC)) {
RETURN_FALSE;
}
}
if ((tmp_name = _rar_entry_get_property(entry_obj, "name", sizeof("name") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
if (!rar || resource_type != le_rar_file) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Rar resource identifier not found");
RETURN_FALSE;
}
extract_data = RAROpenArchive(rar->extract_handle);
if (rar->extract_handle->OpenResult == 0 && extract_data != NULL) {
if (rar->password) {
RARSetPassword(extract_data, rar->password);
}
}
else {
_rar_handle_error(rar->extract_handle->OpenResult TSRMLS_CC);
RETURN_FALSE;
}
while ((result = RARReadHeader(extract_data, &entry)) == 0) {
if (strncmp(entry.FileName,Z_STRVAL_PP(tmp_name), sizeof(entry.FileName)) == 0) {
process_result = RARProcessFile(extract_data, RAR_EXTRACT, path_str, extract_to_file);
RETURN_TRUE;
}
else {
process_result = RARProcessFile(extract_data, RAR_SKIP, NULL, NULL);
}
if (_rar_handle_error(process_result TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
}
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't find file %s in archive %s", Z_STRVAL_PP(tmp_name), rar->extract_handle->ArcName);
RETURN_FALSE;
}
/* }}} */
/* {{{ proto RarEntry::getName();
Return entry name */
PHP_METHOD(rarentry, getName)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "name", sizeof("name") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_string_ex(tmp);
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
/* }}} */
/* {{{ proto RarEntry::getUnpackedSize();
Return unpacked size of the entry */
PHP_METHOD(rarentry, getUnpackedSize)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "unpacked_size", sizeof("unpacked_size") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto RarEntry::getPackedSize();
Return packed size of the entry */
PHP_METHOD(rarentry, getPackedSize)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "packed_size", sizeof("packed_size") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto RarEntry::getHostOs();
Return host OS of the entry */
PHP_METHOD(rarentry, getHostOs)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "host_os", sizeof("host_os") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto RarEntry::getFileTime();
Return modification time of the entry */
PHP_METHOD(rarentry, getFileTime)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "file_time", sizeof("file_time") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_string_ex(tmp);
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
/* }}} */
/* {{{ proto RarEntry::getCrc();
Return CRC of the entry */
PHP_METHOD(rarentry, getCrc)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "crc", sizeof("crc") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_string_ex(tmp);
RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
}
/* }}} */
/* {{{ proto RarEntry::getAttr();
Return attributes of the entry */
PHP_METHOD(rarentry, getAttr)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "attr", sizeof("attr") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto RarEntry::getVersion();
Return version of the archiver, used to create this entry */
PHP_METHOD(rarentry, getVersion)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "version", sizeof("version") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
/* {{{ proto RarEntry::getMethod();
Return packing method */
PHP_METHOD(rarentry, getMethod)
{
zval **rarfile, **tmp;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
if ((tmp = _rar_entry_get_property(entry_obj, "method", sizeof("method") TSRMLS_CC)) == NULL) {
RETURN_FALSE;
}
convert_to_long_ex(tmp);
RETURN_LONG(Z_LVAL_PP(tmp));
}
/* }}} */
#endif /* HAVE_RAR */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/

224
rar_error.c Normal file
View File

@@ -0,0 +1,224 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2009 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
| |
| **** WARNING **** |
| |
| This module makes use of unRAR - free utility for RAR archives. |
| Its license states that you MUST NOT use its code to develop |
| a RAR (WinRAR) compatible archiver. |
| Please, read unRAR license for full information. |
| unRAR & RAR copyrights are owned by Eugene Roshal |
+----------------------------------------------------------------------+
| Author: Antony Dovgal <tony@daylessday.org> |
| Author: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
#include <php.h>
#include <zend_exceptions.h>
#include "php_rar.h"
/* {{{ Globals with external linkage */
zend_class_entry *rarexception_ce_ptr;
/* }}} */
/* Functions with external linkage {{{ */
/* Functions with external linkage {{{ */
int _rar_handle_error(int errcode TSRMLS_DC) /* {{{ */
{
return _rar_handle_error_ex("", errcode TSRMLS_CC);
}
/* }}} */
int _rar_handle_error_ex(const char *preamble, int errcode TSRMLS_DC) /* {{{ */
{
const char *err = _rar_error_to_string(errcode);
if (err == NULL) {
return SUCCESS;
}
if (_rar_using_exceptions(TSRMLS_C)) {
zend_throw_exception_ex(rarexception_ce_ptr, errcode TSRMLS_CC,
"unRAR internal error: %s%s", preamble, err);
}
else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s%s", preamble, err);
}
return FAILURE;
}
/* }}} */
/* Errors not related to the unRAR library */
void _rar_handle_ext_error(const char *format TSRMLS_DC, ...) /* {{{ */
{
va_list arg;
char *message;
va_start(arg, format);
vspprintf(&message, 0, format, arg);
va_end(arg);
if (_rar_using_exceptions(TSRMLS_C))
zend_throw_exception(rarexception_ce_ptr, message, -1L TSRMLS_CC);
else
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", message);
efree(message);
}
/* }}} */
int _rar_using_exceptions(TSRMLS_D)
{
zval *pval;
pval = zend_read_static_property(rarexception_ce_ptr, "usingExceptions",
sizeof("usingExceptions") -1, (zend_bool) 1 TSRMLS_CC);
assert(Z_TYPE_P(pval) == IS_TRUE || Z_TYPE_P(pval) == IS_FALSE);
return Z_TYPE_P(pval) == IS_TRUE;
}
/* returns a string or NULL if not an error */
const char * _rar_error_to_string(int errcode) /* {{{ */
{
const char *ret;
switch (errcode) {
case 0:
/* no error */
case 1:
/* no error (comment completely read) */
case ERAR_END_ARCHIVE:
/* no error */
ret = NULL;
break;
case ERAR_NO_MEMORY:
ret = "ERAR_NO_MEMORY (not enough memory)";
break;
case ERAR_BAD_DATA:
ret = "ERAR_BAD_DATA";
break;
case ERAR_BAD_ARCHIVE:
ret = "ERAR_BAD_ARCHIVE";
break;
case ERAR_UNKNOWN_FORMAT:
ret = "ERAR_UNKNOWN_FORMAT";
break;
case ERAR_EOPEN:
ret = "ERAR_EOPEN (file open error)";
break;
case ERAR_ECREATE:
ret = "ERAR_ECREATE";
break;
case ERAR_ECLOSE:
ret = "ERAR_ECLOSE (error closing file)";
break;
case ERAR_EREAD:
ret = "ERAR_EREAD";
break;
case ERAR_EWRITE:
ret = "ERAR_EWRITE";
break;
case ERAR_SMALL_BUF:
ret = "ERAR_SMALL_BUF";
break;
case ERAR_UNKNOWN:
ret = "ERAR_UNKNOWN (unknown RAR error)";
break;
case ERAR_MISSING_PASSWORD:
ret = "ERAR_MISSING_PASSWORD (password needed but not specified)";
break;
default:
ret = "unknown RAR error (should not happen)";
break;
}
return ret;
}
/* }}} */
/* }}} */
/* {{{ proto bool RarException::setUsingExceptions(using_exceptions)
Set whether exceptions are to be used */
PHP_METHOD(rarexception, setUsingExceptions)
{
zend_bool argval;
int result;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &argval) == FAILURE ) {
return;
}
result = zend_update_static_property_bool(rarexception_ce_ptr,
"usingExceptions", sizeof("usingExceptions") -1,
(long) argval TSRMLS_CC);
if (result == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Could not set error handling mode. "
"This is a bug, please report it.");
return;
}
}
/* }}} */
/* {{{ proto bool RarException::isUsingExceptions()
Return whether exceptions are being used */
PHP_METHOD(rarexception, isUsingExceptions)
{
zval *pval;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE ) {
return;
}
/* or zend_read_static_property, which calls zend_std_get... after chg scope */
zend_string *prop_name =
zend_string_init("usingExceptions", sizeof("usingExceptions") - 1, 0);
pval = zend_std_get_static_property(rarexception_ce_ptr, prop_name,
(zend_bool) 0);
zend_string_release(prop_name);
/* property always exists */
assert(pval != NULL);
assert(Z_TYPE_P(pval) == IS_TRUE || Z_TYPE_P(pval) == IS_FALSE);
RETURN_ZVAL(pval, 0, 0);
}
/* }}} */
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO_EX(arginfo_rarexception_sue, 0, 0, 1)
ZEND_ARG_INFO(0, using_exceptions)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_rarexception_void, 0)
ZEND_END_ARG_INFO()
/* }}} */
/* clang-format off */
static zend_function_entry php_rarexception_class_functions[] = {
PHP_ME(rarexception, setUsingExceptions, arginfo_rarexception_sue, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ME(rarexception, isUsingExceptions, arginfo_rarexception_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
{NULL, NULL, NULL}
};
/* clang-format on */
void minit_rarerror(TSRMLS_D) /* {{{ */
{
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "RarException", php_rarexception_class_functions);
/* zend_exception_get_default() was removed in PHP 8.5; use the global directly */
rarexception_ce_ptr = zend_register_internal_class_ex(&ce, zend_ce_exception);
rarexception_ce_ptr->ce_flags |= ZEND_ACC_FINAL;
zend_declare_property_bool(rarexception_ce_ptr, "usingExceptions",
sizeof("usingExceptions") -1, 0L /* FALSE */,
ZEND_ACC_STATIC TSRMLS_CC);
}
/* }}} */

610
rar_navigation.c Normal file
View File

@@ -0,0 +1,610 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2009 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
| |
| **** WARNING **** |
| |
| This module makes use of unRAR - free utility for RAR archives. |
| Its license states that you MUST NOT use its code to develop |
| a RAR (WinRAR) compatible archiver. |
| Please, read unRAR license for full information. |
| unRAR & RAR copyrights are owned by Eugene Roshal |
+----------------------------------------------------------------------+
| Author: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <php.h>
#include <wchar.h>
#include "php_rar.h"
/* {{{ Structure definitions */
/* clang-format off */
typedef struct _rar_find_state {
rar_find_output out;
rar_file_t *rar;
size_t index; /* next unread in entries_array or entries_array_s */
} rar_find_state;
struct _rar_unique_entry {
size_t id; /* position in the entries_array */
struct RARHeaderDataEx entry; /* last entry */
zend_ulong packed_size;
int depth; /* number of directory separators */
size_t name_wlen; /* excluding L'\0' terminator */
};
/* last_accessed has the index of the last accessed entry. Its purpose is to make
* more efficient the situation wherein the user traverses a directory and
* stats each the gotten entry in each iteration. This gives 100% cache hits in
* directory traversal tests 064 and 065 for exact name searches */
struct _rar_entries {
size_t num_entries;
struct _rar_unique_entry **entries_array; /* shoud not be NULL */
struct _rar_unique_entry **entries_array_s; /* sorted version for bsearch */
struct _rar_unique_entry *last_accessed;
int list_result; /* tell whether the archive's broken */
};
/* clang-format on */
/* }}} */
/* {{{ Function prototypes for functions with internal linkage */
static void _rar_nav_get_depth_and_length(wchar_t *filenamew, const size_t file_size,
int *depth_out, size_t *wlen_out TSRMLS_DC);
static int _rar_nav_get_depth(const wchar_t *filenamew, const size_t file_size);
static int _rar_nav_compare_entries(const void *op1, const void *op2 TSRMLS_DC);
static void _rar_nav_swap_entries(void *op1, void *op2);
static int _rar_nav_compare_entries_std(const void *op1, const void *op2);
static inline int _rar_nav_compare_values(const wchar_t *str1, const int depth1,
const wchar_t *str2, const int depth2,
const size_t max_size);
static int _rar_nav_directory_match(const wchar_t *dir, const size_t dir_len,
const wchar_t *entry, const size_t entry_len);
static size_t _rar_nav_position_on_dir_start(const wchar_t *dir_name,
int dir_depth,
size_t dir_size,
struct _rar_unique_entry **entries,
size_t low, size_t high);
/* }}} */
/* {{{ Functions with external linkage */
/* {{{ _rar_entry_count */
size_t _rar_entry_count(rar_file_t *rar) {
return rar->entries->num_entries;
}
/* }}} */
/* {{{ _rar_entry_search_start */
void _rar_entry_search_start(rar_file_t *rar,
unsigned mode,
rar_find_output **state TSRMLS_DC)
{
rar_find_state **out = (rar_find_state **) state;
assert(out != NULL);
*out = ecalloc(1, sizeof **out);
(*out)->rar = rar;
(*out)->out.position = -1;
assert(rar->entries != NULL);
assert(rar->entries->num_entries == 0 || rar->entries->entries_array != NULL);
if ((mode & 0x02U) && (rar->entries->num_entries > 0) &&
(rar->entries->entries_array_s == NULL)) {
rar->entries->entries_array_s = emalloc(rar->entries->num_entries *
sizeof rar->entries->entries_array_s[0]);
memcpy(rar->entries->entries_array_s, rar->entries->entries_array,
rar->entries->num_entries * sizeof rar->entries->entries_array[0]);
zend_qsort(rar->entries->entries_array_s, rar->entries->num_entries,
sizeof *rar->entries->entries_array_s, _rar_nav_compare_entries,
_rar_nav_swap_entries);
}
}
/* }}} */
/* {{{ _rar_entry_search_seek */
void _rar_entry_search_seek(rar_find_output *state, size_t pos)
{
rar_find_state *rstate = (rar_find_state *) state;
assert(pos >= 0);
rstate->out.eof = 0;
rstate->out.found = 0;
rstate->out.position = -1;
rstate->out.header = NULL;
rstate->out.packed_size = 0;
rstate->index = pos;
}
/* }}} */
/* {{{ _rar_entry_search_end */
void _rar_entry_search_end(rar_find_output *state)
{
if (state) {
/* may not have been initialized due to error conditions
* in rararch_it_get_iterator that jumped out of the function */
efree(state);
}
}
/* }}} */
/* {{{ _rar_entry_search_rewind */
void _rar_entry_search_rewind(rar_find_output *state)
{
rar_find_state *rstate = (rar_find_state *) state;
rstate->out.eof = 0;
rstate->out.found = 0;
rstate->out.position = -1;
rstate->out.header = NULL;
rstate->out.packed_size = 0;
rstate->index = 0;
}
/* }}} */
/* {{{ _rar_entry_search_advance */
void _rar_entry_search_advance(rar_find_output *state,
const wchar_t * const file, /* NULL = give next */
size_t file_size, /* length + 1; 0 if unknown */
int directory_match)
{
rar_find_state *rstate = (rar_find_state *) state;
struct _rar_entries *entries;
int found = FALSE;
int in_sorted;
size_t filenamewsize;
assert(state != NULL);
assert(file == NULL || file_size == 0 || file[file_size - 1] == L'\0');
entries = rstate->rar->entries;
assert(entries != NULL);
if ((file != NULL) && (file_size == 0))
file_size = wcslen(file) + 1;
/* reset output */
memset(&rstate->out, 0, sizeof rstate->out);
filenamewsize = sizeof(entries->entries_array[0]->entry.FileNameW) /
sizeof(entries->entries_array[0]->entry.FileNameW[0]); /* = 1024 */
if (rstate->out.eof || (rstate->index >= entries->num_entries) ||
(file_size > filenamewsize)) {
rstate->out.found = 0;
rstate->out.eof = 1;
return;
}
/* three different cases:
* (1) ask next
* (2) ask by name
* (3) ask next directory child */
if (!directory_match && (file == NULL)) {
/* ask next */
in_sorted = FALSE;
found = TRUE;
/* populate cache for exact name access */
entries->last_accessed = entries->entries_array[rstate->index];
}
else if (!directory_match) {
/* ask by exact name */
struct _rar_unique_entry temp_entry,
*temp_entry_ptr = &temp_entry,
**found_entry;
/* try to hit cache */
if (entries->last_accessed != NULL) {
if ((entries->last_accessed->name_wlen == file_size - 1) &&
wmemcmp(entries->last_accessed->entry.FileNameW, file,
file_size) == 0) {
/* cache hit */
in_sorted = FALSE;
found = TRUE;
rstate->index = entries->last_accessed->id;
/*php_printf("cache hit\n", entries);*/
}
else {
entries->last_accessed = NULL;
/*php_printf("cache miss\n", entries);*/
}
}
/*else
php_printf("cache miss (empty)\n", entries);*/
if (!found) { /* the cache didn't do; use binary search */
wmemcpy(temp_entry.entry.FileNameW, file, file_size);
temp_entry.depth = _rar_nav_get_depth(file, file_size);
found_entry = bsearch(&temp_entry_ptr,
&entries->entries_array_s[rstate->index],
entries->num_entries - rstate->index,
sizeof entries->entries_array_s[0],
_rar_nav_compare_entries_std);
if (found_entry != NULL) {
in_sorted = TRUE;
found = TRUE;
rstate->index = found_entry - entries->entries_array_s;
}
}
}
else {
/* ask by next directory child */
struct _rar_unique_entry *cur = entries->entries_array_s[rstate->index];
in_sorted = TRUE;
assert(file != NULL);
if (_rar_nav_directory_match(file, file_size - 1,
cur->entry.FileNameW, cur->name_wlen)) {
found = TRUE;
/* populate cache for exact name access */
entries->last_accessed = cur;
}
else {
/* no directory match for current */
int comp, dir_depth;
dir_depth = _rar_nav_get_depth(file, file_size);
comp = _rar_nav_compare_values(cur->entry.FileNameW, cur->depth,
file, dir_depth + 1, file_size); /* guaranteed file_size <= 1024 */
assert(comp != 0); /* because + 1 was summed to the depth */
if (comp > 0) {
/* past the entries of the directory */
/* do nothing */
}
else {
int pos = _rar_nav_position_on_dir_start(file, dir_depth,
file_size, entries->entries_array_s, rstate->index,
entries->num_entries);
if (pos != -1) {
found = TRUE;
rstate->index = pos;
/* populate cache for exact name access */
entries->last_accessed = entries->entries_array_s[pos];
}
}
}
}
if (found == FALSE) {
rstate->out.found = 0;
rstate->out.eof = 1;
}
else {
struct _rar_unique_entry *cur;
if (in_sorted)
cur = entries->entries_array_s[rstate->index];
else
cur = entries->entries_array[rstate->index];
rstate->out.found = 1;
rstate->out.position = cur->id;
rstate->out.header = &cur->entry;
rstate->out.packed_size = cur->packed_size;
rstate->index++;
}
}
/* }}} */
/* {{{ _rar_delete_entries - accepts an allocated entries list */
void _rar_delete_entries(rar_file_t *rar TSRMLS_DC)
{
if (rar->entries != NULL) {
if (rar->entries->entries_array != NULL) {
size_t i;
for (i = 0; i < rar->entries->num_entries; i++) {
if (rar->entries->entries_array[i]->entry.RedirName != NULL) {
efree(rar->entries->entries_array[i]->entry.RedirName);
}
efree(rar->entries->entries_array[i]);
}
efree(rar->entries->entries_array);
if (rar->entries->entries_array_s != NULL)
efree(rar->entries->entries_array_s);
}
efree(rar->entries);
}
}
/* }}} */
/* guarantees correct initialization of rar->entries on failure
* If the passed rar_file_t structure has the allow_broken option, it
* always returns success (ERAR_END_ARCHIVE) */
int _rar_list_files(rar_file_t *rar TSRMLS_DC) /* {{{ */
{
int result = 0;
size_t capacity = 0;
int first_file_check = TRUE;
zend_ulong packed_size = 0;
struct _rar_entries *ents;
if (rar->entries != NULL) {
/* we've already listed this file's entries */
if (rar->allow_broken)
return ERAR_END_ARCHIVE;
else
return rar->entries->list_result;
}
assert(rar->entries == NULL);
rar->entries = emalloc(sizeof *rar->entries);
ents = rar->entries;
ents->num_entries = 0;
ents->entries_array = NULL;
ents->entries_array_s = NULL;
ents->last_accessed = NULL;
while (result == 0) {
struct _rar_unique_entry *ue;
struct RARHeaderDataEx entry = {0};
wchar_t redir_name[1024] = L"";
entry.RedirName = redir_name;
entry.RedirNameSize = sizeof(redir_name) / sizeof(redir_name[0]);
result = RARReadHeaderEx(rar->arch_handle, &entry);
/* value of 2nd argument is irrelevant in RAR_OM_LIST_[SPLIT] mode */
if (result == 0) {
result = RARProcessFile(rar->arch_handle, RAR_SKIP, NULL, NULL);
}
if (result != 0)
break;
if (first_file_check) {
if (entry.Flags & RHDF_SPLITBEFORE)
continue;
else
first_file_check = FALSE;
}
/* reset packed size if not split before */
if ((entry.Flags & RHDF_SPLITBEFORE) == 0)
packed_size = 0;
/* accumulate packed size; cap at ZEND_LONG_MAX (the PHP int ceiling) */
{
zend_ulong entry_packed = ((zend_ulong)entry.PackSizeHigh << 32) | entry.PackSize;
if (entry_packed > (zend_ulong)ZEND_LONG_MAX ||
packed_size > (zend_ulong)ZEND_LONG_MAX - entry_packed)
packed_size = (zend_ulong)ZEND_LONG_MAX;
else
packed_size += entry_packed;
}
if (entry.Flags & RHDF_SPLITAFTER) /* do not commit */
continue;
/* commit the entry */
assert(capacity >= ents->num_entries);
if (capacity == ents->num_entries) { /* 0, 2, 6, 14, 30... */
capacity = (capacity + 1) * 2;
ents->entries_array = safe_erealloc(ents->entries_array, capacity,
sizeof(*ents->entries_array), 0);
}
assert(capacity > ents->num_entries);
ents->entries_array[ents->num_entries] = ue =
emalloc(sizeof *ents->entries_array[0]);
memcpy(&ue->entry, &entry, sizeof ents->entries_array[0]->entry);
ue->id = ents->num_entries;
ue->packed_size = packed_size;
_rar_nav_get_depth_and_length(entry.FileNameW,
sizeof(entry.FileNameW) / sizeof(entry.FileNameW[0]), /* = 1024 */
&ue->depth, &ue->name_wlen TSRMLS_CC);
if (redir_name[0] != L'\0') {
size_t size = (wcslen(redir_name) + 1) * sizeof(redir_name[0]);
ue->entry.RedirName = emalloc(size);
memcpy(ue->entry.RedirName, redir_name, size);
} else {
ue->entry.RedirName = NULL;
ue->entry.RedirNameSize = 0;
}
ents->num_entries++;
}
rar->entries->list_result = result;
return rar->allow_broken ? ERAR_END_ARCHIVE : result;
}
/* }}} */
/* end functions with external linkage }}} */
/* {{{ Functions with internal linkage */
static void _rar_nav_get_depth_and_length(wchar_t *filenamew, const size_t file_size,
int *depth_out, size_t *wlen_out TSRMLS_DC) /* {{{ */
{
size_t i;
int depth = 0;
assert(file_size >= 1);
for (i = 0; i < file_size; i++) {
if (filenamew[i] == L'\0')
break;
if (filenamew[i] == SPATHDIVIDER[0])
depth++;
}
if (i == file_size) { /* should not happen */
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"The library gave an unterminated file name. "
"This is a bug, please report it.");
i--;
filenamew[i] = L'\0';
}
if ((i >= 1) && (filenamew[i-1] == SPATHDIVIDER[0])) {
/* entry name ended in path divider. shouldn't happen */
i--;
filenamew[i] = L'\0';
depth--;
}
*depth_out = depth;
if (wlen_out != NULL)
*wlen_out = (size_t) i;
}
/* }}} */
static int _rar_nav_get_depth(const wchar_t *filenamew, const size_t file_size) /* {{{ */
{
size_t i;
int depth = 0;
for (i = 0; i < file_size; i++) {
if (filenamew[i] == L'\0')
break;
if (filenamew[i] == SPATHDIVIDER[0])
depth++;
}
assert(i < file_size);
return depth;
}
/* }}} */
static int _rar_nav_compare_entries(const void *op1, const void *op2 TSRMLS_DC) /* {{{ */
{
const struct _rar_unique_entry *a = *((struct _rar_unique_entry **) op1),
*b = *((struct _rar_unique_entry **) op2);
return _rar_nav_compare_values(a->entry.FileNameW, a->depth,
b->entry.FileNameW, b->depth,
sizeof(a->entry.FileNameW) / sizeof(a->entry.FileNameW[0]) /*1024*/);
}
/* }}} */
static void _rar_nav_swap_entries(void *op1, void *op2) /* {{{ */
{
/* just swaps two pointer values */
struct _rar_unique_entry **a = op1,
**b = op2,
*tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
/* }}} */
static int _rar_nav_compare_entries_std(const void *op1, const void *op2) /* {{{ */
{
const struct _rar_unique_entry *a = *((struct _rar_unique_entry **) op1),
*b = *((struct _rar_unique_entry **) op2);
return _rar_nav_compare_values(a->entry.FileNameW, a->depth,
b->entry.FileNameW, b->depth,
sizeof(a->entry.FileNameW) / sizeof(a->entry.FileNameW[0]) /*1024*/);
}
/* }}} */
static inline int _rar_nav_compare_values(const wchar_t *str1, const int depth1,
const wchar_t *str2, const int depth2,
const size_t max_size) /* {{{ */
{
if (depth1 == depth2) {
return wcsncmp(str1, str2, max_size);
}
else {
return depth1 > depth2 ? 1 : -1;
}
}
/* }}} */
/* does not assume null termination */
static int _rar_nav_directory_match(const wchar_t *dir, const size_t dir_len,
const wchar_t *entry, const size_t entry_len) /* {{{ */
{
const wchar_t *chr,
*entry_rem;
size_t entry_rem_len;
/* dir does not end with the path separator */
if (dir_len > 0) {
if (entry_len <= dir_len) /* don't match the dir itself */
return FALSE;
/* assert(entry_len > dir_len > 0) */
if (wmemcmp(dir, entry, dir_len) != 0)
return FALSE;
/* directory name does not follow path sep or path sep ends the name */
if (entry[dir_len] != SPATHDIVIDER[0] || entry_len == dir_len + 1)
return FALSE;
/* assert(entry_len > dir_len + 1) */
entry_rem = &entry[dir_len + 1];
entry_rem_len = entry_len - (dir_len + 1);
}
else {
entry_rem = entry;
entry_rem_len = entry_len;
}
chr = wmemchr(entry_rem, SPATHDIVIDER[0], entry_rem_len);
/* must have no / after the directory */
return (chr == NULL);
}
/* }}} */
static size_t _rar_nav_position_on_dir_start(const wchar_t *dir_name,
int dir_depth,
size_t dir_size,
struct _rar_unique_entry **entries,
size_t low, size_t high) /* {{{ */
{
size_t mid;
int comp;
size_t orig_high = high;
if (dir_size == 1) { /* root */
if (low >= high)
return -1;
if (entries[low]->depth == 0)
return low;
else
return -1;
}
while (low < high) {
mid = low + (high - low) / 2;
comp = _rar_nav_compare_values(dir_name, dir_depth + 1,
entries[mid]->entry.FileNameW, entries[mid]->depth,
dir_size);
if (comp > 0)
low = mid + 1;
else
high = mid;
}
if (low >= orig_high)
return -1;
if (_rar_nav_directory_match(dir_name, dir_size - 1,
entries[low]->entry.FileNameW, entries[low]->name_wlen))
return low;
else
return -1;
}
/* }}} */
/* end functions with internal linkage */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/

1264
rar_stream.c Normal file

File diff suppressed because it is too large Load Diff

55
rar_time.c Normal file
View File

@@ -0,0 +1,55 @@
#include <php.h>
#include "php_rar.h"
void rar_time_convert(unsigned low, unsigned high, time_t *to) /* {{{ */
{
time_t default_ = (time_t) 0,
local_time;
struct tm tm = {0};
TSRMLS_FETCH();
if (high == 0U && low == 0U) {
*to = default_;
return;
}
/* 11644473600000000000 - number of ns between 01-01-1601 and 01-01-1970. */
uint64 ushift=INT32TO64(0xA1997B0B,0x4C6A0000);
/* value is in 10^-7 seconds since 01-01-1601 */
/* convert to nanoseconds, shift to 01-01-1970 and convert to seconds */
local_time = (time_t) ((INT32TO64(high, low) * 100 - ushift) / 1000000000);
/* now we have the time in... I don't know what. It gives UTC - tz offset */
/* we need to try and convert it to UTC */
/* abuse gmtime, which is supposed to work with UTC */
if (php_gmtime_r(&local_time, &tm) == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Could not convert time to UTC, using local time");
*to = local_time;
}
tm.tm_isdst = -1;
*to = local_time + (local_time - mktime(&tm));
}
/* }}} */
int rar_dos_time_convert(unsigned dos_time, time_t *to) /* {{{ */
{
struct tm time_s = {0};
time_s.tm_sec = (dos_time & 0x1f)*2;
time_s.tm_min = (dos_time>>5) & 0x3f;
time_s.tm_hour = (dos_time>>11) & 0x1f;
time_s.tm_mday = (dos_time>>16) & 0x1f;
time_s.tm_mon = ((dos_time>>21) & 0x0f) - 1;
time_s.tm_year = (dos_time>>25) + 80;
/* the dos times that unrar gives out seem to be already in UTC.
* Or at least they don't depend on TZ */
if ((*to = timegm(&time_s)) == (time_t) -1) {
return FAILURE;
}
return SUCCESS;
}
/* }}} */

1096
rararch.c Normal file

File diff suppressed because it is too large Load Diff

826
rarentry.c Normal file
View File

@@ -0,0 +1,826 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2009 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_0.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
| |
| **** WARNING **** |
| |
| This module makes use of unRAR - free utility for RAR archives. |
| Its license states that you MUST NOT use its code to develop |
| a RAR (WinRAR) compatible archiver. |
| Please, read unRAR license for full information. |
| unRAR & RAR copyrights are owned by Eugene Roshal |
+----------------------------------------------------------------------+
| Author: Antony Dovgal <tony@daylessday.org> |
| Author: Gustavo Lopes <cataphract@php.net> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#include <zend_types.h>
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <string.h>
#include <php.h>
#include "php_rar.h"
/* {{{ Globals with external linkage */
zend_class_entry *rar_class_entry_ptr;
/* }}} */
/* {{{ Function prototypes for functions with internal linkage */
static int _rar_decl_priv_prop_null(zend_class_entry *ce, const char *name,
int name_length, char *doc_comment,
int doc_comment_len TSRMLS_DC);
static zval *_rar_entry_get_property(zval *entry_obj, char *name, int namelen TSRMLS_DC);
static void _rar_dos_date_to_text(unsigned dos_time, char *date_string);
/* }}} */
/* {{{ Functions with external linkage */
/* should be passed the last entry that corresponds to a given file
* only that one has the correct CRC. Still, it may have a wrong packedSize */
/* parent is zval to RarArchive object. The object
* will have its refcount increased */
void _rar_entry_to_zval(zval *parent,
struct RARHeaderDataEx *entry,
zend_ulong packed_size,
size_t position,
zval *object TSRMLS_DC)
/* {{{ */
{
char tmp_s [MAX_LENGTH_OF_LONG + 1];
char time[50];
char *filename;
int filename_size,
filename_len;
zend_long unp_size;
zval *parent_copy = parent;
object_init_ex(object, rar_class_entry_ptr);
#if PHP_MAJOR_VERSION >= 8
zend_object *obj = Z_OBJ_P(object);
#else
zval *obj = object;
#endif
zend_update_property(rar_class_entry_ptr, obj, "rarfile",
sizeof("rararch") - 1, parent_copy TSRMLS_CC);
{
uint64_t raw_size = (uint64_t)entry->UnpSizeHigh << 32 | entry->UnpSize;
unp_size = raw_size > (uint64_t)ZEND_LONG_MAX
? ZEND_LONG_MAX : (zend_long)raw_size;
}
filename_size = sizeof(entry->FileNameW) * 4;
filename = (char*) emalloc(filename_size);
if (packed_size > (zend_ulong) ZEND_LONG_MAX)
packed_size = (zend_ulong) ZEND_LONG_MAX;
_rar_wide_to_utf(entry->FileNameW, filename, filename_size);
/* OK; safe usage below: */
filename_len = _rar_strnlen(filename, filename_size);
/* we're not in class scope, so we cannot change the class private
* properties from here with add_property_x, or
* direct call to rarentry_object_handlers.write_property
* zend_update_property_x updates the scope accordingly */
zend_update_property_long(rar_class_entry_ptr, obj, "position",
sizeof("position") - 1, (zend_long) position TSRMLS_CC);
zend_update_property_stringl(rar_class_entry_ptr, obj, "name",
sizeof("name") - 1, filename, filename_len TSRMLS_CC);
zend_update_property_long(rar_class_entry_ptr, obj, "unpacked_size",
sizeof("unpacked_size") - 1, unp_size TSRMLS_CC);
zend_update_property_long(rar_class_entry_ptr, obj, "packed_size",
sizeof("packed_size") - 1, packed_size TSRMLS_CC);
zend_update_property_long(rar_class_entry_ptr, obj, "host_os",
sizeof("host_os") - 1, entry->HostOS TSRMLS_CC);
_rar_dos_date_to_text(entry->FileTime, time);
zend_update_property_string(rar_class_entry_ptr, obj, "file_time",
sizeof("file_time") - 1, time TSRMLS_CC);
sprintf(tmp_s, "%x", entry->FileCRC);
zend_update_property_string(rar_class_entry_ptr, obj, "crc",
sizeof("crc") - 1, tmp_s TSRMLS_CC);
zend_update_property_long(rar_class_entry_ptr, obj, "attr",
sizeof("attr") - 1, entry->FileAttr TSRMLS_CC);
zend_update_property_long(rar_class_entry_ptr, obj, "version",
sizeof("version") - 1, entry->UnpVer TSRMLS_CC);
zend_update_property_long(rar_class_entry_ptr, obj, "method",
sizeof("method") - 1, entry->Method TSRMLS_CC);
zend_update_property_long(rar_class_entry_ptr, obj, "flags",
sizeof("flags") - 1, entry->Flags TSRMLS_CC);
zend_update_property_long(rar_class_entry_ptr, obj, "redir_type",
sizeof("redir_type") - 1, entry->RedirType TSRMLS_CC);
if (entry->RedirName) {
char *redir_target = NULL;
size_t redir_target_size;
zend_update_property_bool(rar_class_entry_ptr, obj,
"redir_to_directory", sizeof("redir_to_directory") - 1,
!!entry->DirTarget TSRMLS_CC);
redir_target_size = entry->RedirNameSize * 4;
redir_target = emalloc(redir_target_size);
assert(redir_target_size > 0);
_rar_wide_to_utf(entry->RedirName, redir_target, redir_target_size);
zend_update_property_string(rar_class_entry_ptr, obj, "redir_target",
sizeof("redir_target") - 1, redir_target TSRMLS_CC);
efree(redir_target);
}
efree(filename);
}
/* }}} */
/* }}} */
/* {{{ Helper functions and preprocessor definitions */
#define RAR_GET_PROPERTY(var, prop_name) \
if (!entry_obj) { \
php_error_docref(NULL TSRMLS_CC, E_WARNING, "this method cannot be called statically"); \
RETURN_FALSE; \
} \
if ((var = _rar_entry_get_property(entry_obj, prop_name, \
sizeof(prop_name) - 1 TSRMLS_CC)) == NULL) { \
RETURN_FALSE; \
}
#define REG_RAR_CLASS_CONST_LONG(const_name, value) \
zend_declare_class_constant_long(rar_class_entry_ptr, const_name, \
sizeof(const_name) - 1, (zend_long) value TSRMLS_CC)
#define REG_RAR_PROPERTY(name, comment) \
_rar_decl_priv_prop_null(rar_class_entry_ptr, name, sizeof(name) -1, \
comment, sizeof(comment) - 1 TSRMLS_CC)
static int _rar_decl_priv_prop_null(zend_class_entry *ce, const char *name,
int name_length, char *doc_comment,
int doc_comment_len TSRMLS_DC) /* {{{ */
{
zval property;
zend_string *name_str,
*doc_str;
int ret;
ZVAL_NULL(&property);
name_str = zend_string_init(name, (size_t) name_length, 1);
doc_str = zend_string_init(doc_comment, (size_t) doc_comment_len, 1);
# if PHP_MAJOR_VERSION >= 8
zend_declare_property_ex(ce, name_str, &property, ZEND_ACC_PRIVATE,
doc_str);
ret = SUCCESS;
# else
ret = zend_declare_property_ex(ce, name_str, &property, ZEND_ACC_PRIVATE,
doc_str);
#endif
zend_string_release(name_str);
zend_string_release(doc_str);
return ret;
}
/* }}} */
static zval *_rar_entry_get_property(zval *entry_obj, char *name, int namelen TSRMLS_DC) /* {{{ */
{
zval *tmp;
zval zv;
#if PHP_VERSION_ID < 70100
zend_class_entry *orig_scope = EG(scope);
EG(scope) = rar_class_entry_ptr;
#endif
#if PHP_MAJOR_VERSION >= 8
tmp = zend_read_property(Z_OBJCE_P(entry_obj), Z_OBJ_P(entry_obj), name, namelen, 1, &zv);
#else
tmp = zend_read_property(Z_OBJCE_P(entry_obj), entry_obj, name, namelen, 1, &zv);
#endif
if (tmp == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Bug: unable to find property '%s'. Please report.", name);
}
#if PHP_VERSION_ID < 70100
EG(scope) = orig_scope;
#endif
return tmp;
}
/* }}} */
static void _rar_dos_date_to_text(unsigned dos_time, char *date_string) /* {{{ */
{
time_t time = 0;
struct tm tm = {0};
int res;
res = rar_dos_time_convert(dos_time, &time) != FAILURE &&
php_gmtime_r(&time, &tm) != NULL;
if (!res) {
sprintf(date_string, "%s", "time conversion failure");
}
sprintf(date_string, "%u-%02u-%02u %02u:%02u:%02u",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min,
tm.tm_sec);
}
/* }}} */
/* }}} */
/* {{{ Methods */
/* {{{ public function extract(?string $dir, ?string $filepath = '',
?string $password = null, bool $extended_data = false): void {}
Extract file from the archive */
PHP_METHOD(rarentry, extract)
{ /* lots of variables, but no need to be intimidated */
char *dir,
*filepath = NULL,
*password = NULL;
zpp_s_size_t dir_len,
filepath_len = 0,
password_len = 0;
char *considered_path;
char considered_path_res[MAXPATHLEN];
int with_second_arg;
zend_bool process_ed = 0;
zval *tmp,
*tmp_position;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
struct RARHeaderDataEx entry = {0};
HANDLE extract_handle = NULL;
int result;
int found;
/* gotta have a new copy (shallow is enough) because we may want to use a
* password that's different from the one stored in the rar_file_t object*/
rar_cb_user_data cb_udata = {NULL};
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!|s!s!b", &dir,
&dir_len, &filepath, &filepath_len, &password, &password_len,
&process_ed) == FAILURE ) {
return;
}
RAR_GET_PROPERTY(tmp, "rarfile");
if (_rar_get_file_resource_zv(tmp, &rar TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
/* Decide where to extract */
with_second_arg = (filepath_len != 0);
/* the arguments are mutually exclusive.
* If the second is specified, we ignore the first */
if (!with_second_arg) {
if (dir_len == 0) /* both params empty */
dir = ".";
considered_path = dir;
}
else {
considered_path = filepath;
}
if (OPENBASEDIR_CHECKPATH(considered_path)) {
RETURN_FALSE;
}
if (!expand_filepath(considered_path, considered_path_res TSRMLS_CC)) {
RETURN_FALSE;
}
/* Find file inside archive */
RAR_GET_PROPERTY(tmp_position, "position");
/* don't set the new password now because maybe the headers are
* encrypted with a password different from this file's (though WinRAR
* does not support that: if you encrypt the headers, you must encrypt
* the files with the same password). By not replacing the password
* now, we're using the password given to rar_open, if any (which must
* have enabled decrypting the headers or else we wouldn't be here) */
memcpy(&cb_udata, &rar->cb_userdata, sizeof cb_udata);
result = _rar_find_file_p(rar->extract_open_data,
(size_t) Z_LVAL_P(tmp_position), &cb_udata, &extract_handle, &found,
&entry);
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
RETVAL_FALSE;
goto cleanup;
}
if (!found) {
_rar_handle_ext_error("Can't find file with index %d in archive %s"
TSRMLS_CC, Z_LVAL_P(tmp_position),
rar->extract_open_data->ArcName);
RETVAL_FALSE;
goto cleanup;
}
RARSetProcessExtendedData(extract_handle, (int) process_ed);
/* now use the password given to this method. If none was given, we're
* still stuck with the password given to rar_open, if any */
if (password != NULL)
cb_udata.password = password;
/* Do extraction */
if (!with_second_arg)
result = RARProcessFile(extract_handle, RAR_EXTRACT,
considered_path_res, NULL);
else
result = RARProcessFile(extract_handle, RAR_EXTRACT,
NULL, considered_path_res);
if (_rar_handle_error(result TSRMLS_CC) == FAILURE) {
RETVAL_FALSE;
}
else {
RETVAL_TRUE;
}
cleanup:
if (extract_handle != NULL)
RARCloseArchive(extract_handle);
}
/* }}} */
/* {{{ proto int RarEntry::getPosiiton()
Return position for the entry */
PHP_METHOD(rarentry, getPosition)
{
zval *tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "position");
RETURN_LONG(Z_LVAL_P(tmp));
}
/* }}} */
/* {{{ proto string RarEntry::getName()
Return entry name */
PHP_METHOD(rarentry, getName)
{
zval *tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "name");
RAR_RETURN_STRINGL(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), 1);
}
/* }}} */
/* {{{ proto int RarEntry::getUnpackedSize()
Return unpacked size of the entry */
PHP_METHOD(rarentry, getUnpackedSize)
{
zval *tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "unpacked_size");
RETURN_LONG(Z_LVAL_P(tmp));
}
/* }}} */
/* {{{ proto int RarEntry::getPackedSize()
Return packed size of the entry */
PHP_METHOD(rarentry, getPackedSize)
{
zval *tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "packed_size");
RETURN_LONG(Z_LVAL_P(tmp));
}
/* }}} */
/* {{{ proto int RarEntry::getHostOs()
Return host OS of the entry */
PHP_METHOD(rarentry, getHostOs)
{
zval *tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "host_os");
RETURN_LONG(Z_LVAL_P(tmp));
}
/* }}} */
/* {{{ proto string RarEntry::getFileTime()
Return modification time of the entry.
Due to the way the unrar library returns this time, this is in the
system's timezone. */
PHP_METHOD(rarentry, getFileTime)
{
zval *tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "file_time");
RAR_RETURN_STRINGL(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), 1);
}
/* }}} */
/* {{{ proto string RarEntry::getCrc()
Return CRC of the entry */
PHP_METHOD(rarentry, getCrc)
{
zval *tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "crc");
RAR_RETURN_STRINGL(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), 1);
}
/* }}} */
/* {{{ proto int RarEntry::getAttr()
Return attributes of the entry */
PHP_METHOD(rarentry, getAttr)
{
zval *tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "attr");
RETURN_LONG(Z_LVAL_P(tmp));
}
/* }}} */
/* {{{ proto int RarEntry::getVersion()
Return version of the archiver, used to create this entry */
PHP_METHOD(rarentry, getVersion)
{
zval *tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "version");
RETURN_LONG(Z_LVAL_P(tmp));
}
/* }}} */
/* {{{ proto int RarEntry::getMethod()
Return packing method */
PHP_METHOD(rarentry, getMethod)
{
zval *tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "method");
RETURN_LONG(Z_LVAL_P(tmp));
}
/* }}} */
/* {{{ proto resource RarEntry::getStream([string password = NULL])
Return stream for current entry */
PHP_METHOD(rarentry, getStream)
{
zval *tmp,
*position;
rar_file_t *rar = NULL;
zval *entry_obj = getThis();
php_stream *stream = NULL;
char *password = NULL;
zpp_s_size_t password_len; /* ignored */
rar_cb_user_data cb_udata = {NULL};
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!",
&password, &password_len) == FAILURE ) {
return;
}
RAR_GET_PROPERTY(position, "position");
RAR_GET_PROPERTY(tmp, "rarfile");
if (_rar_get_file_resource_zv(tmp, &rar TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
}
/* use rar_open password (stored in rar->cb_userdata) by default */
memcpy(&cb_udata, &rar->cb_userdata, sizeof cb_udata);
if (password != NULL)
cb_udata.password = password;
/* doesn't matter that cb_udata is stack allocated, it will be copied */
stream = php_stream_rar_open(rar->extract_open_data->ArcName,
Z_LVAL_P(position), &cb_udata STREAMS_CC TSRMLS_CC);
if (stream != NULL) {
php_stream_to_zval(stream, return_value);
}
else
RETVAL_FALSE;
}
/* }}} */
/* {{{ proto int RarEntry::isDirectory()
Return whether the entry represents a directory */
PHP_METHOD(rarentry, isDirectory)
{
zval *tmp;
zval *entry_obj = getThis();
zend_long flags;
int is_dir;
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "flags");
flags = Z_LVAL_P(tmp);
is_dir = (flags & RHDF_DIRECTORY) != 0;
RETURN_BOOL(is_dir);
}
/* }}} */
/* {{{ proto int RarEntry::isEncrypted()
Return whether the entry is encrypted and needs a password */
PHP_METHOD(rarentry, isEncrypted)
{
zval *tmp;
zval *entry_obj = getThis();
zend_long flags;
int is_encrypted;
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "flags");
flags = Z_LVAL_P(tmp);
is_encrypted = (flags & RHDF_ENCRYPTED) != 0;
RETURN_BOOL(is_encrypted);
}
/* }}} */
/* {{{ proto int RarEntry::getRedirType()
Returns the redirection type, or NULL if there's none */
PHP_METHOD(rarentry, getRedirType)
{
zval *tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "redir_type");
if (Z_TYPE_P(tmp) != IS_LONG) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "bad redir type stored");
RETURN_FALSE;
}
if (Z_LVAL_P(tmp) == FSREDIR_NONE) {
RETURN_NULL();
}
RETURN_LONG(Z_LVAL_P(tmp));
}
/* }}} */
/* {{{ proto bool RarEntry::isRedirectToDirectory()
Returns true if there is redirection and the target is a directory,
null if there is no redirection, false otherwise */
PHP_METHOD(rarentry, isRedirectToDirectory)
{
zval *tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "redir_to_directory");
RETURN_ZVAL(tmp, 1, 0);
}
/* }}} */
/* {{{ proto bool RarEntry::getRedirTarget()
Returns the redirection target, encoded as UTF-8, or NULL */
PHP_METHOD(rarentry, getRedirTarget)
{
zval *tmp;
zval *entry_obj = getThis();
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(tmp, "redir_target");
RETURN_ZVAL(tmp, 1, 0);
}
/* }}} */
/* {{{ proto string RarEntry::__toString()
Return string representation for entry */
PHP_METHOD(rarentry, __toString)
{
zval *flags_zval,
*name_zval,
*crc_zval;
zval *entry_obj = getThis();
long flags;
int is_dir;
char *name,
*crc;
char *restring;
int restring_size;
const char format[] = "RarEntry for %s \"%s\" (%s)";
RAR_RETNULL_ON_ARGS();
RAR_GET_PROPERTY(flags_zval, "flags");
flags = Z_LVAL_P(flags_zval);
is_dir = flags & RHDF_DIRECTORY;
RAR_GET_PROPERTY(name_zval, "name");
name = Z_STRVAL_P(name_zval);
RAR_GET_PROPERTY(crc_zval, "crc");
crc = Z_STRVAL_P(crc_zval);
/* 2 is size of %s, 8 is size of crc */
restring_size = (sizeof(format)-1) - 2 * 3 + (sizeof("directory")-1) +
strlen(name) + 8 + 1;
restring = emalloc(restring_size);
snprintf(restring, restring_size, format, is_dir?"directory":"file",
name, crc);
restring[restring_size - 1] = '\0'; /* just to be safe */
RAR_RETURN_STRINGL(restring, strlen(restring), 0);
}
/* }}} */
/* }}} */
/* {{{ arginfo */
#if PHP_MAJOR_VERSION < 8
ZEND_BEGIN_ARG_INFO_EX(arginfo_rarentry_extract, 0, 0, 1)
ZEND_ARG_INFO(0, path)
ZEND_ARG_INFO(0, filename)
ZEND_ARG_INFO(0, password)
ZEND_ARG_INFO(0, extended_data)
ZEND_END_ARG_INFO()
#else
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_rarentry_extract, 0, 1, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(0, dir, IS_STRING, 1)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, filepath, IS_STRING, 1, "\'\'")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, password, IS_STRING, 1, "null")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, extended_data, _IS_BOOL, 0, "false")
ZEND_END_ARG_INFO()
#endif
ZEND_BEGIN_ARG_INFO_EX(arginfo_rarentry_getstream, 0, 0, 0)
ZEND_ARG_INFO(0, password)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_rar_void, 0)
ZEND_END_ARG_INFO()
#if PHP_VERSION_ID >= 80200
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_rar_tostring, 0, 0, IS_STRING, 0)
ZEND_END_ARG_INFO()
#else
#define arginfo_rar_tostring arginfo_rar_void
#endif
/* }}} */
/* clang-format off */
static zend_function_entry php_rar_class_functions[] = {
PHP_ME(rarentry, extract, arginfo_rarentry_extract, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getPosition, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getName, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getUnpackedSize, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getPackedSize, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getHostOs, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getFileTime, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getCrc, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getAttr, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getVersion, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getMethod, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getStream, arginfo_rarentry_getstream, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, isDirectory, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, isEncrypted, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getRedirType, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, isRedirectToDirectory, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, getRedirTarget, arginfo_rar_void, ZEND_ACC_PUBLIC)
PHP_ME(rarentry, __toString, arginfo_rar_tostring, ZEND_ACC_PUBLIC)
PHP_ME_MAPPING(__construct, rar_bogus_ctor, arginfo_rar_void, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR)
{NULL, NULL, NULL}
};
/* clang-format on */
void minit_rarentry(TSRMLS_D)
{
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "RarEntry", php_rar_class_functions);
rar_class_entry_ptr = zend_register_internal_class(&ce TSRMLS_CC);
rar_class_entry_ptr->ce_flags |= ZEND_ACC_FINAL_CLASS;
rar_class_entry_ptr->clone = NULL;
REG_RAR_PROPERTY("rarfile", "Associated RAR archive");
REG_RAR_PROPERTY("position", "Position inside the RAR archive");
REG_RAR_PROPERTY("name", "File or directory name with path");
REG_RAR_PROPERTY("unpacked_size", "Size of file when unpacked");
REG_RAR_PROPERTY("packed_size", "Size of the packed file inside the archive");
REG_RAR_PROPERTY("host_os", "OS used to pack the file");
REG_RAR_PROPERTY("file_time", "Entry's time of last modification");
REG_RAR_PROPERTY("crc", "CRC checksum for the unpacked file");
REG_RAR_PROPERTY("attr", "OS-dependent file attributes");
REG_RAR_PROPERTY("version", "RAR version needed to extract entry");
REG_RAR_PROPERTY("method", "Identifier for packing method");
REG_RAR_PROPERTY("flags", "Entry header flags");
REG_RAR_PROPERTY("redir_type", "The type of redirection or NULL");
REG_RAR_PROPERTY("redir_to_directory", "Whether the redirection target is a directory");
REG_RAR_PROPERTY("redir_target", "Target of the redirectory");
/* clang-format off */
REG_RAR_CLASS_CONST_LONG("HOST_MSDOS", HOST_MSDOS);
REG_RAR_CLASS_CONST_LONG("HOST_OS2", HOST_OS2);
REG_RAR_CLASS_CONST_LONG("HOST_WIN32", HOST_WIN32);
REG_RAR_CLASS_CONST_LONG("HOST_UNIX", HOST_UNIX);
REG_RAR_CLASS_CONST_LONG("HOST_MACOS", HOST_MACOS);
REG_RAR_CLASS_CONST_LONG("HOST_BEOS", HOST_BEOS);
REG_RAR_CLASS_CONST_LONG("FSREDIR_UNIXSYMLINK", FSREDIR_UNIXSYMLINK);
REG_RAR_CLASS_CONST_LONG("FSREDIR_WINSYMLINK", FSREDIR_WINSYMLINK);
REG_RAR_CLASS_CONST_LONG("FSREDIR_JUNCTION", FSREDIR_JUNCTION);
REG_RAR_CLASS_CONST_LONG("FSREDIR_HARDLINK", FSREDIR_HARDLINK);
REG_RAR_CLASS_CONST_LONG("FSREDIR_FILECOPY", FSREDIR_FILECOPY);
/* see WinNT.h */
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_READONLY", 0x00001L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_HIDDEN", 0x00002L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_SYSTEM", 0x00004L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_DIRECTORY", 0x00010L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_ARCHIVE", 0x00020L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_DEVICE", 0x00040L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_NORMAL", 0x00080L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_TEMPORARY", 0x00100L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_SPARSE_FILE", 0x00200L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_REPARSE_POINT", 0x00400L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_COMPRESSED", 0x00800L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_OFFLINE", 0x01000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_NOT_CONTENT_INDEXED", 0x02000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_ENCRYPTED", 0x04000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_WIN_VIRTUAL", 0x10000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_WORLD_EXECUTE", 0x00001L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_WORLD_WRITE", 0x00002L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_WORLD_READ", 0x00004L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_GROUP_EXECUTE", 0x00008L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_GROUP_WRITE", 0x00010L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_GROUP_READ", 0x00020L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_OWNER_EXECUTE", 0x00040L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_OWNER_WRITE", 0x00080L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_OWNER_READ", 0x00100L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_STICKY", 0x00200L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_SETGID", 0x00400L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_SETUID", 0x00800L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_FINAL_QUARTET", 0x0F000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_FIFO", 0x01000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_CHAR_DEV", 0x02000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_DIRECTORY", 0x04000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_BLOCK_DEV", 0x06000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_REGULAR_FILE", 0x08000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_SYM_LINK", 0x0A000L);
REG_RAR_CLASS_CONST_LONG("ATTRIBUTE_UNIX_SOCKET", 0x0C000L);
/* clang-format on */
}

3797
run-tests-rar.php Normal file

File diff suppressed because it is too large Load Diff

275
technote.txt Normal file
View File

@@ -0,0 +1,275 @@
RAR version 3.93 - Technical information
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
THE ARCHIVE FORMAT DESCRIBED BELOW IS ONLY VALID FOR VERSIONS SINCE 1.50
==========================================================================
RAR archive file format
==========================================================================
Archive file consists of variable length blocks. The order of these
blocks may vary, but the first block must be a marker block followed by
an archive header block.
Each block begins with the following fields:
HEAD_CRC 2 bytes CRC of total block or block part
HEAD_TYPE 1 byte Block type
HEAD_FLAGS 2 bytes Block flags
HEAD_SIZE 2 bytes Block size
ADD_SIZE 4 bytes Optional field - added block size
Field ADD_SIZE present only if (HEAD_FLAGS & 0x8000) != 0
Total block size is HEAD_SIZE if (HEAD_FLAGS & 0x8000) == 0
and HEAD_SIZE+ADD_SIZE if the field ADD_SIZE is present - when
(HEAD_FLAGS & 0x8000) != 0.
In each block the followings bits in HEAD_FLAGS have the same meaning:
0x4000 - if set, older RAR versions will ignore the block
and remove it when the archive is updated.
if clear, the block is copied to the new archive
file when the archive is updated;
0x8000 - if set, ADD_SIZE field is present and the full block
size is HEAD_SIZE+ADD_SIZE.
Declared block types:
HEAD_TYPE=0x72 marker block
HEAD_TYPE=0x73 archive header
HEAD_TYPE=0x74 file header
HEAD_TYPE=0x75 old style comment header
HEAD_TYPE=0x76 old style authenticity information
HEAD_TYPE=0x77 old style subblock
HEAD_TYPE=0x78 old style recovery record
HEAD_TYPE=0x79 old style authenticity information
HEAD_TYPE=0x7a subblock
Comment block is actually used only within other blocks and doesn't
exist separately.
Archive processing is made in the following manner:
1. Read and check marker block
2. Read archive header
3. Read or skip HEAD_SIZE-sizeof(MAIN_HEAD) bytes
4. If end of archive encountered then terminate archive processing,
else read 7 bytes into fields HEAD_CRC, HEAD_TYPE, HEAD_FLAGS,
HEAD_SIZE.
5. Check HEAD_TYPE.
if HEAD_TYPE==0x74
read file header ( first 7 bytes already read )
read or skip HEAD_SIZE-sizeof(FILE_HEAD) bytes
if (HEAD_FLAGS & 0x100)
read or skip HIGH_PACK_SIZE*0x100000000+PACK_SIZE bytes
else
read or skip PACK_SIZE bytes
else
read corresponding HEAD_TYPE block:
read HEAD_SIZE-7 bytes
if (HEAD_FLAGS & 0x8000)
read ADD_SIZE bytes
6. go to 4.
==========================================================================
Block Formats
==========================================================================
Marker block ( MARK_HEAD )
HEAD_CRC Always 0x6152
2 bytes
HEAD_TYPE Header type: 0x72
1 byte
HEAD_FLAGS Always 0x1a21
2 bytes
HEAD_SIZE Block size = 0x0007
2 bytes
The marker block is actually considered as a fixed byte
sequence: 0x52 0x61 0x72 0x21 0x1a 0x07 0x00
Archive header ( MAIN_HEAD )
HEAD_CRC CRC of fields HEAD_TYPE to RESERVED2
2 bytes
HEAD_TYPE Header type: 0x73
1 byte
HEAD_FLAGS Bit flags:
2 bytes
0x0001 - Volume attribute (archive volume)
0x0002 - Archive comment present
RAR 3.x uses the separate comment block
and does not set this flag.
0x0004 - Archive lock attribute
0x0008 - Solid attribute (solid archive)
0x0010 - New volume naming scheme ('volname.partN.rar')
0x0020 - Authenticity information present
RAR 3.x does not set this flag.
0x0040 - Recovery record present
0x0080 - Block headers are encrypted
0x0100 - First volume (set only by RAR 3.0 and later)
other bits in HEAD_FLAGS are reserved for
internal use
HEAD_SIZE Archive header total size including archive comments
2 bytes
RESERVED1 Reserved
2 bytes
RESERVED2 Reserved
4 bytes
File header (File in archive)
HEAD_CRC CRC of fields from HEAD_TYPE to FILEATTR
2 bytes and file name
HEAD_TYPE Header type: 0x74
1 byte
HEAD_FLAGS Bit flags:
2 bytes
0x01 - file continued from previous volume
0x02 - file continued in next volume
0x04 - file encrypted with password
0x08 - file comment present
RAR 3.x uses the separate comment block
and does not set this flag.
0x10 - information from previous files is used (solid flag)
(for RAR 2.0 and later)
bits 7 6 5 (for RAR 2.0 and later)
0 0 0 - dictionary size 64 KB
0 0 1 - dictionary size 128 KB
0 1 0 - dictionary size 256 KB
0 1 1 - dictionary size 512 KB
1 0 0 - dictionary size 1024 KB
1 0 1 - dictionary size 2048 KB
1 1 0 - dictionary size 4096 KB
1 1 1 - file is directory
0x100 - HIGH_PACK_SIZE and HIGH_UNP_SIZE fields
are present. These fields are used to archive
only very large files (larger than 2Gb),
for smaller files these fields are absent.
0x200 - FILE_NAME contains both usual and encoded
Unicode name separated by zero. In this case
NAME_SIZE field is equal to the length
of usual name plus encoded Unicode name plus 1.
If this flag is present, but FILE_NAME does not
contain zero bytes, it means that file name
is encoded using UTF-8.
0x400 - the header contains additional 8 bytes
after the file name, which are required to
increase encryption security (so called 'salt').
0x800 - Version flag. It is an old file version,
a version number is appended to file name as ';n'.
0x1000 - Extended time field present.
0x8000 - this bit always is set, so the complete
block size is HEAD_SIZE + PACK_SIZE
(and plus HIGH_PACK_SIZE, if bit 0x100 is set)
HEAD_SIZE File header full size including file name and comments
2 bytes
PACK_SIZE Compressed file size
4 bytes
UNP_SIZE Uncompressed file size
4 bytes
HOST_OS Operating system used for archiving
1 byte 0 - MS DOS
1 - OS/2
2 - Win32
3 - Unix
4 - Mac OS
5 - BeOS
FILE_CRC File CRC
4 bytes
FTIME Date and time in standard MS DOS format
4 bytes
UNP_VER RAR version needed to extract file
1 byte
Version number is encoded as
10 * Major version + minor version.
METHOD Packing method
1 byte
0x30 - storing
0x31 - fastest compression
0x32 - fast compression
0x33 - normal compression
0x34 - good compression
0x35 - best compression
NAME_SIZE File name size
2 bytes
ATTR File attributes
4 bytes
HIGH_PACK_SIZE High 4 bytes of 64 bit value of compressed file size.
4 bytes Optional value, presents only if bit 0x100 in HEAD_FLAGS
is set.
HIGH_UNP_SIZE High 4 bytes of 64 bit value of uncompressed file size.
4 bytes Optional value, presents only if bit 0x100 in HEAD_FLAGS
is set.
FILE_NAME File name - string of NAME_SIZE bytes size
SALT present if (HEAD_FLAGS & 0x400) != 0
8 bytes
EXT_TIME present if (HEAD_FLAGS & 0x1000) != 0
variable size
other new fields may appear here.
==========================================================================
Application notes
==========================================================================
1. To process an SFX archive you need to skip the SFX module searching
for the marker block in the archive. There is no marker block sequence (0x52
0x61 0x72 0x21 0x1a 0x07 0x00) in the SFX module itself.
2. The CRC is calculated using the standard polynomial 0xEDB88320. In
case the size of the CRC is less than 4 bytes, only the low order bytes
are used.

View File

@@ -11,8 +11,17 @@ var_dump($rar_file1);
$rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
var_dump($rar_file2);
$rar_file3 = rar_open(dirname(__FILE__).'/no_such_file.rar');
var_dump($rar_file3);
echo "Done\n";
?>
--EXPECTF--
resource(%d) of type (Rar)
resource(%d) of type (Rar)
object(RarArchive)#%d (%d) {
}
object(RarArchive)#%d (%d) {
}
Warning: rar_open(): Failed to open %sno_such_file.rar: ERAR_EOPEN (file open error) in %s on line %d
bool(false)
Done

View File

@@ -5,6 +5,7 @@ rar_list() function
--FILE--
<?php
require __DIR__ . "/php8compat.php.inc";
$rar_file1 = rar_open(dirname(__FILE__).'/linux_rar.rar');
$list1 = rar_list($rar_file1);
var_dump($list1);
@@ -13,102 +14,154 @@ $rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
$list2 = rar_list($rar_file2);
var_dump($list2);
$rar_file3 = rar_open(dirname(__FILE__).'/no_such_file.rar');
argerr(function() use ($rar_file3) { rar_list($rar_file3); });
echo "Done\n";
?>
--EXPECTF--
array(2) {
[0]=>
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#%d (%d) {
}
["position%sprivate%s=>
int(0)
["name%sprivate%s=>
string(9) "plain.txt"
["unpacked_size"]=>
["unpacked_size%sprivate%s=>
int(15)
["packed_size"]=>
["packed_size%sprivate%s=>
int(25)
["host_os"]=>
["host_os%sprivate%s=>
int(3)
["file_time"]=>
["file_time%sprivate%s=>
string(19) "2004-06-11 11:01:24"
["crc"]=>
["crc%sprivate%s=>
string(8) "7728b6fe"
["attr"]=>
["attr%sprivate%s=>
int(33188)
["version"]=>
["version%sprivate%s=>
int(29)
["method"]=>
["method%sprivate%s=>
int(51)
["flags%sprivate%s=>
int(0)
["redir_type%sprivate]=>
int(0)
["redir_to_directory%sprivate]=>
NULL
["redir_target%sprivate]=>
NULL
}
[1]=>
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#%d (%d) {
}
["position%sprivate%s=>
int(1)
["name%sprivate%s=>
string(30) "test file with whitespaces.txt"
["unpacked_size"]=>
["unpacked_size%sprivate%s=>
int(14)
["packed_size"]=>
["packed_size%sprivate%s=>
int(20)
["host_os"]=>
["host_os%sprivate%s=>
int(3)
["file_time"]=>
["file_time%sprivate%s=>
string(19) "2004-06-11 11:01:32"
["crc"]=>
["crc%sprivate%s=>
string(8) "21890dd9"
["attr"]=>
["attr%sprivate%s=>
int(33188)
["version"]=>
["version%sprivate%s=>
int(29)
["method"]=>
["method%sprivate%s=>
int(51)
["flags%sprivate%s=>
int(0)
["redir_type%sprivate]=>
int(0)
["redir_to_directory%sprivate]=>
NULL
["redir_target%sprivate]=>
NULL
}
}
array(2) {
[0]=>
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#%d (%d) {
}
["position%sprivate%s=>
int(0)
["name%sprivate%s=>
string(5) "1.txt"
["unpacked_size"]=>
["unpacked_size%sprivate%s=>
int(5)
["packed_size"]=>
["packed_size%sprivate%s=>
int(17)
["host_os"]=>
["host_os%sprivate%s=>
int(2)
["file_time"]=>
["file_time%sprivate%s=>
string(19) "2004-06-11 10:07:18"
["crc"]=>
["crc%sprivate%s=>
string(8) "a0de71c0"
["attr"]=>
["attr%sprivate%s=>
int(32)
["version"]=>
["version%sprivate%s=>
int(29)
["method"]=>
["method%sprivate%s=>
int(53)
["flags%sprivate%s=>
int(0)
["redir_type%sprivate]=>
int(0)
["redir_to_directory%sprivate]=>
NULL
["redir_target%sprivate]=>
NULL
}
[1]=>
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#%d (%d) {
}
["position%sprivate%s=>
int(1)
["name%sprivate%s=>
string(5) "2.txt"
["unpacked_size"]=>
["unpacked_size%sprivate%s=>
int(5)
["packed_size"]=>
["packed_size%sprivate%s=>
int(16)
["host_os"]=>
["host_os%sprivate%s=>
int(2)
["file_time"]=>
["file_time%sprivate%s=>
string(19) "2004-06-11 10:07:26"
["crc"]=>
["crc%sprivate%s=>
string(8) "45a918de"
["attr"]=>
["attr%sprivate%s=>
int(32)
["version"]=>
["version%sprivate%s=>
int(29)
["method"]=>
["method%sprivate%s=>
int(53)
["flags%sprivate%s=>
int(16)
["redir_type%sprivate]=>
int(0)
["redir_to_directory%sprivate]=>
NULL
["redir_target%sprivate]=>
NULL
}
}
Warning: rar_open(): Failed to open %s: ERAR_EOPEN (file open error) in %s on line %d
Warning: rar_list() expects parameter 1 to be RarArchive, %s given in %s on line %d
Done

View File

@@ -5,6 +5,7 @@ rar_entry_get() function
--FILE--
<?php
require __DIR__ . "/php8compat.php.inc";
$rar_file1 = rar_open(dirname(__FILE__).'/linux_rar.rar');
$entry1 = rar_entry_get($rar_file1, 'test file with whitespaces.txt');
var_dump($entry1);
@@ -13,52 +14,82 @@ $rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
$entry2 = rar_entry_get($rar_file2, '2.txt');
var_dump($entry2);
$rar_file3 = rar_open(dirname(__FILE__).'/no_such_file.rar');
argerr(function() use ($rar_file3) {
rar_entry_get($rar_file3, '2.txt');
});
echo "Done\n";
?>
--EXPECTF--
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#%d (%d) {
}
["position%sprivate%s=>
int(1)
["name%sprivate%s=>
string(30) "test file with whitespaces.txt"
["unpacked_size"]=>
["unpacked_size%sprivate%s=>
int(14)
["packed_size"]=>
["packed_size%sprivate%s=>
int(20)
["host_os"]=>
["host_os%sprivate%s=>
int(3)
["file_time"]=>
["file_time%sprivate%s=>
string(19) "2004-06-11 11:01:32"
["crc"]=>
["crc%sprivate%s=>
string(8) "21890dd9"
["attr"]=>
["attr%sprivate%s=>
int(33188)
["version"]=>
["version%sprivate%s=>
int(29)
["method"]=>
["method%sprivate%s=>
int(51)
["flags%sprivate%s=>
int(0)
["redir_type%sprivate%s=>
int(0)
["redir_to_directory%sprivate%s=>
NULL
["redir_target%sprivate%s=>
NULL
}
object(RarEntry)#%d (10) {
["rarfile"]=>
resource(%d) of type (Rar)
["name"]=>
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#%d (%d) {
}
["position%sprivate%s=>
int(1)
["name%sprivate%s=>
string(5) "2.txt"
["unpacked_size"]=>
["unpacked_size%sprivate%s=>
int(5)
["packed_size"]=>
["packed_size%sprivate%s=>
int(16)
["host_os"]=>
["host_os%sprivate%s=>
int(2)
["file_time"]=>
["file_time%sprivate%s=>
string(19) "2004-06-11 10:07:26"
["crc"]=>
["crc%sprivate%s=>
string(8) "45a918de"
["attr"]=>
["attr%sprivate%s=>
int(32)
["version"]=>
["version%sprivate%s=>
int(29)
["method"]=>
["method%sprivate%s=>
int(53)
["flags%sprivate%s=>
int(16)
["redir_type%sprivate%s=>
int(0)
["redir_to_directory%sprivate%s=>
NULL
["redir_target%sprivate%s=>
NULL
}
Warning: rar_open(): Failed to open %s: ERAR_EOPEN (file open error) in %s on line %d
Warning: rar_entry_get() expects parameter 1 to be RarArchive, %s given in %s on line %d
Done

View File

@@ -11,10 +11,12 @@ $entry1 = rar_entry_get($rar_file1, 'test file with whitespaces.txt');
$entry1->extract(dirname(__FILE__));
$contents11 = file_get_contents(dirname(__FILE__).'/test file with whitespaces.txt');
echo $contents11."\n";
@unlink(dirname(__FILE__).'/test file with whitespaces.txt');
$entry1->extract(false,dirname(__FILE__).'/1.txt');
$contents12 = file_get_contents(dirname(__FILE__).'/1.txt');
echo $contents12."\n";
@unlink(dirname(__FILE__).'/1.txt');
$rar_file2 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
$entry2 = rar_entry_get($rar_file2, '2.txt');
@@ -22,19 +24,67 @@ $entry2 = rar_entry_get($rar_file2, '2.txt');
$entry2->extract(dirname(__FILE__));
$contents21 = file_get_contents(dirname(__FILE__).'/2.txt');
echo $contents21."\n";
@unlink(dirname(__FILE__).'/2.txt');
$entry2->extract(false,dirname(__FILE__).'/some.txt');
$contents22 = file_get_contents(dirname(__FILE__).'/some.txt');
echo $contents22."\n";
@unlink(dirname(__FILE__).'/test file with whitespaces.txt');
@unlink(dirname(__FILE__).'/1.txt');
@unlink(dirname(__FILE__).'/2.txt');
@unlink(dirname(__FILE__).'/some.txt');
$entry2->extract(dirname(__FILE__));
var_dump(file_get_contents(dirname(__FILE__).'/2.txt'));
@unlink(dirname(__FILE__).'/2.txt');
$oldcwd = getcwd();
chdir(dirname(__FILE__));
var_dump($entry2);
var_dump($entry2->extract("",""));
@unlink('2.txt');
chdir($oldcwd);
echo "Done\n";
?>
--EXPECTF--
blah-blah-blah
blah-blah-blah
22222
22222
string(5) "22222"
object(RarEntry)#%d (%d) {
["rarfile%sprivate%s=>
object(RarArchive)#%d (%d) {
}
["position%sprivate%s=>
int(1)
["name%sprivate%s=>
string(5) "2.txt"
["unpacked_size%sprivate%s=>
int(5)
["packed_size%sprivate%s=>
int(16)
["host_os%sprivate%s=>
int(2)
["file_time%sprivate%s=>
string(19) "2004-06-11 10:07:26"
["crc%sprivate%s=>
string(8) "45a918de"
["attr%sprivate%s=>
int(32)
["version%sprivate%s=>
int(29)
["method%sprivate%s=>
int(53)
["flags%sprivate%s=>
int(16)
["redir_type%sprivate%s=>
int(0)
["redir_to_directory%sprivate%s=>
NULL
["redir_target%sprivate%s=>
NULL
}
bool(true)
Done

36
tests/005.phpt Normal file
View File

@@ -0,0 +1,36 @@
--TEST--
rar_comment_get() function
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/commented.rar');
var_export(rar_comment_get($rar_file1));
echo "\n";
var_export(rar_comment_get($rar_file1));
echo "\n";
var_export($rar_file1->getComment());
echo "\n";
$rar_file2 = rar_open(dirname(__FILE__).'/linux_rar.rar');
var_export(rar_comment_get($rar_file2));
echo "\n";
rar_close($rar_file2);
var_export(rar_comment_get($rar_file2));
echo "\n";
echo "Done\n";
?>
--EXPECTF--
'This is the comment of the file commented.rar.'
'This is the comment of the file commented.rar.'
'This is the comment of the file commented.rar.'
NULL
Warning: rar_comment_get(): The archive is already closed in %s on line %d
false
Done

22
tests/006.phpt Normal file
View File

@@ -0,0 +1,22 @@
--TEST--
RarEntry::getCrc() method in multi-volume archives (PECL bug #9470)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/multi.part1.rar');
$list = rar_list($rar_file1);
echo $list[0]->getCrc()."\n";
echo $list[1]->getCrc()."\n";
echo $list[2]->getCrc()."\n";
echo "\n";
echo "Done\n";
?>
--EXPECTF--
52b28202
f2c79881
bcbce32e
Done

18
tests/007.phpt Normal file
View File

@@ -0,0 +1,18 @@
--TEST--
rar_open() function with a non-RAR
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/rar_notrar.rar');
var_dump($rar_file1);
echo "\n";
echo "Done\n";
?>
--EXPECTF--
Warning: rar_open(): Failed to open %s: ERAR_BAD_ARCHIVE in %s on line %d
bool(false)
Done

36
tests/008.phpt Normal file
View File

@@ -0,0 +1,36 @@
--TEST--
rar_entry_get() function
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
require __DIR__ . "/php8compat.php.inc";
$rar_file1 = rar_open(dirname(__FILE__).'/multi.part1.rar');
$entry = rar_entry_get($rar_file1, "file1.txt");
echo "$entry\n";
$entry = rar_entry_get($rar_file1, "nonexistent_file.txt");
var_dump($entry);
echo "\n";
$rar_file2 = rar_open(dirname(__FILE__).'/nonexistent.rar');
argerr(function() use ($rar_file2) {
rar_entry_get($rar_file2, "file1.txt");
});
echo "\n";
echo "Done\n";
?>
--EXPECTF--
RarEntry for file "file1.txt" (52b28202)
Warning: rar_entry_get(): cannot find file "nonexistent_file.txt" in Rar archive "%s" in %s on line %d
bool(false)
Warning: rar_open(): Failed to open %s: ERAR_EOPEN (file open error) in %s on line %d
Warning: rar_entry_get() expects parameter 1 to be RarArchive, %s given in %s on line %d
Done

19
tests/009.phpt Normal file
View File

@@ -0,0 +1,19 @@
--TEST--
RarEntry::getName() function with unicode filenames
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/rar_unicode.rar');
$entries = rar_list($rar_file1);
$name = reset($entries)->getName();
var_dump($name);
echo "\n";
echo "Done\n";
?>
--EXPECTF--
string(13) "file1À۞.txt"
Done

32
tests/010.phpt Normal file
View File

@@ -0,0 +1,32 @@
--TEST--
RarEntry::getStream() function (good RAR file, one volume)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/latest_winrar.rar');
$entries = rar_list($rar_file1);
echo count($entries)." files:\n\n";
//var_dump($entries);
foreach ($entries as $e) {
$stream = $e->getStream();
echo $e->getName().":\n";
while (!feof($stream)) {
echo fread($stream, 8192);
}
echo "\n\n";
}
echo "Done\n";
?>
--EXPECTF--
2 files:
1.txt:
11111
2.txt:
22222
Done

45
tests/011.phpt Normal file
View File

@@ -0,0 +1,45 @@
--TEST--
RarEntry::getStream() function (good RAR file, several volumes)
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
if(PHP_INT_SIZE < 8) die("skip 32-bit PHP not supported");
?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/multi.part1.rar');
$entries = rar_list($rar_file1);
echo count($entries)." files:\n\n";
//var_dump($entries);
function int32_to_hex($value) {
$value &= 0xffffffff;
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
}
foreach ($entries as $e) {
$stream = $e->getStream();
if ($stream === false) {
die("Failed to get stream.\n");
break;
}
echo $e->getName().": ";
$a = "";
while (!feof($stream)) {
$a .= fread($stream, 8192);
}
echo strlen($a)." bytes, CRC ";
echo int32_to_hex(crc32($a))."\n\n"; //you can confirm they're equal to those given by $e->getCrc()
}
echo "Done\n";
?>
--EXPECTF--
3 files:
file1.txt: 18 bytes, CRC 52B28202
file2.txt: 17704 bytes, CRC F2C79881
file3.txt: 18 bytes, CRC BCBCE32E
Done

41
tests/012.phpt Normal file
View File

@@ -0,0 +1,41 @@
--TEST--
RarEntry::getStream() function (bad RAR file)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/corrupted.rar');
$entries = rar_list($rar_file1);
echo count($entries)." files (will test only the first 4):\n\n";
//var_dump($entries);
$i = 0;
foreach ($entries as $e) {
if ($i++ >= 2)
break;
//$e->extract(false, dirname(__FILE__).'/temp.txt');
//echo "now stream\n";
$stream = $e->getStream();
echo $e->getName().": ";
if ($stream === false) {
echo "Could not get stream.\n\n";
continue;
}
while (!feof($stream) && $i != 2) {
echo fread($stream, 8192);
}
fclose($stream);
echo "\n";
}
echo "Done\n";
?>
--EXPECTF--
51 files (will test only the first 4):
test%s: The great battle of Gunprex versus Optiter!!!!!1
Gunprex, Fire!
So long, Optiter!
test%s
Done

20
tests/013.phpt Normal file
View File

@@ -0,0 +1,20 @@
--TEST--
rar_entry_get() and RarEntry::getName() coherence
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/rar_unicode.rar');
$entries = rar_list($rar_file1);
$name = reset($entries)->getName();
$entryback = rar_entry_get($rar_file1, $name);
echo "$entryback\n";
echo "\n";
echo "Done\n";
?>
--EXPECTF--
RarEntry for file "file1À۞.txt" (52b28202)
Done

26
tests/014.phpt Normal file
View File

@@ -0,0 +1,26 @@
--TEST--
RarEntry::getStream() on unicode entry
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/rar_unicode.rar');
$entry = rar_entry_get($rar_file1, "file1À۞.txt");
echo $entry."\n";
echo "\n";
$stream = $entry->getStream();
if ($stream !== false)
while (!feof($stream)) {
echo fread($stream, 8192);
}
echo "\n";
echo "Done\n";
?>
--EXPECTF--
RarEntry for file "file1À۞.txt" (52b28202)
contents of file 1
Done

30
tests/015.phpt Normal file
View File

@@ -0,0 +1,30 @@
--TEST--
rar_close() liberates resource (PECL bug #9649)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
copy(dirname(__FILE__).'/latest_winrar.rar', dirname(__FILE__).'/temp.rar');
$rar_file1 = rar_open(dirname(__FILE__).'/temp.rar');
echo $rar_file1."\n";
$entries = rar_list($rar_file1);
$entry1 = reset($entries);
unset($entries);
echo $entry1."\n";
echo "\n";
rar_close($rar_file1);
echo $rar_file1."\n";
$entry1->extract(".");
unlink(dirname(__FILE__).'/temp.rar');
echo "Done\n";
?>
--EXPECTF--
RAR Archive "%s"
RarEntry for file "1.txt" (a0de71c0)
RAR Archive "%s" (closed)
Warning: RarEntry::extract(): The archive is already closed in %s on line %d
Done

50
tests/016.phpt Normal file
View File

@@ -0,0 +1,50 @@
--TEST--
RarEntry::extract() method (corrupt RAR file)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/corrupted.rar');
$entries = rar_list($rar_file1);
echo count($entries)." files (will test only the first 4):\n\n";
//var_dump($entries);
$i = 0;
foreach ($entries as $e) {
if ($i++ >= 4)
break;
echo "Extraction of file #$i:\n";
$ret = $e->extract(false, dirname(__FILE__).'/temp.txt');
if ($ret)
echo "\tSUCCESS\n";
else
echo "\tFAILED\n";
echo "\n";
}
@unlink(dirname(__FILE__).'/temp.txt');
echo "Done\n";
?>
--EXPECTF--
51 files (will test only the first 4):
Extraction of file #1:
SUCCESS
Extraction of file #2:
Warning: RarEntry::extract(): ERAR_BAD_DATA in %s on line %d
FAILED
Extraction of file #3:
Warning: RarEntry::extract(): ERAR_BAD_DATA in %s on line %d
FAILED
Extraction of file #4:
Warning: RarEntry::extract(): ERAR_BAD_DATA in %s on line %d
FAILED
Done

22
tests/017.phpt Normal file
View File

@@ -0,0 +1,22 @@
--TEST--
RarEntry::extract() with unicode files
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/rar_unicode.rar');
$entries = rar_list($rar_file1);
$e = reset($entries);
$e->extract(false, dirname(__FILE__).'/temp.txt');
echo file_get_contents(dirname(__FILE__).'/temp.txt');
echo "\n";
@unlink(dirname(__FILE__).'/temp.txt');
echo "Done\n";
?>
--EXPECTF--
contents of file 1
Done

24
tests/018.phpt Normal file
View File

@@ -0,0 +1,24 @@
--TEST--
rar_list()/rar_entry_get() with not first volume
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/multi.part2.rar');
$entries = rar_list($rar_file1);
echo "Number of entries: " . count($entries) . "\n";
echo reset($entries)."\n";
$e = rar_entry_get($rar_file1, "file2.txt");
var_dump($e);
$e = rar_entry_get($rar_file1, "file3.txt");
echo $e."\n";
echo "Done\n";
--EXPECTF--
Number of entries: 1
RarEntry for file "file3.txt" (bcbce32e)
Warning: rar_entry_get(): cannot find file "file2.txt" in Rar archive "%s in %s on line %d
bool(false)
RarEntry for file "file3.txt" (bcbce32e)
Done

37
tests/019.phpt Normal file
View File

@@ -0,0 +1,37 @@
--TEST--
RarEntry::getStream() function (store method)
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
if(PHP_INT_SIZE < 8) die("skip 32-bit PHP not supported");
?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/store_method.rar');
$entries = rar_list($rar_file1);
echo count($entries)." files:\n\n";
//var_dump($entries);
function int32_to_hex($value) {
$value &= 0xffffffff;
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
}
foreach ($entries as $e) {
$stream = $e->getStream();
echo $e->getName().": ";
$a = "";
while (!feof($stream)) {
$a .= fread($stream, 512);
}
echo strlen($a)." bytes, CRC ";
echo int32_to_hex(crc32($a))."\n\n"; //you can confirm they're equal to those given by $e->getCrc()
}
echo "Done\n";
?>
--EXPECTF--
1 files:
tese.txt: 787 bytes, CRC 23B93A7A
Done

39
tests/020.phpt Normal file
View File

@@ -0,0 +1,39 @@
--TEST--
RarEntry::getStream() function (solid archive)
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
if(PHP_INT_SIZE < 8) die("skip 32-bit PHP not supported");
?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/solid.rar');
$entries = rar_list($rar_file1);
echo count($entries)." files:\n\n";
//var_dump($entries);
function int32_to_hex($value) {
$value &= 0xffffffff;
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
}
foreach ($entries as $e) {
$stream = $e->getStream();
echo $e->getName().": ";
$a = "";
while (!feof($stream)) {
$a .= fread($stream, 8192);
}
echo strlen($a)." bytes, CRC ";
echo int32_to_hex(crc32($a))."\n\n"; //you can confirm they're equal to those given by $e->getCrc()
}
echo "Done\n";
?>
--EXPECTF--
2 files:
tese.txt: 787 bytes, CRC 23B93A7A
unrardll.txt: 19192 bytes, CRC 2ED64B6E
Done

19
tests/021.phpt Normal file
View File

@@ -0,0 +1,19 @@
--TEST--
RarEntry::isDirectory() basic test
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/directories.rar');
$entries = rar_list($rar_file1);
foreach ($entries as $e) {
echo "{$e->getName()} is ". ($e->isDirectory()?"":"not ") . "a directory.\n";
}
echo "Done\n";
--EXPECTF--
dirwithsth%cfileindir.txt is not a directory.
dirwithsth is a directory.
emptydir is a directory.
Done

40
tests/022.phpt Normal file
View File

@@ -0,0 +1,40 @@
--TEST--
RarEntry::extract() with directory
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/directories.rar');
$e = rar_entry_get($rar_file1, "emptydir");
$dir = dirname(__FILE__) . DIRECTORY_SEPARATOR . "emptydir";
$exists = is_dir($dir);
var_dump($exists);
$extrres = $e->extract(dirname(__FILE__));
var_dump($extrres);
$exists = is_dir($dir);
var_dump($exists);
@rmdir($dir);
echo "\n\n";
$dir = dirname(__FILE__) . DIRECTORY_SEPARATOR . "emptydircust";
$exists = is_dir($dir);
var_dump($exists);
$extrres = $e->extract(false, $dir);
var_dump($extrres);
$exists = is_dir($dir);
var_dump($exists);
@rmdir($dir);
echo "Done\n";
--EXPECTF--
bool(false)
bool(true)
bool(true)
bool(false)
bool(true)
bool(true)
Done

21
tests/023.phpt Normal file
View File

@@ -0,0 +1,21 @@
--TEST--
RarEntry::getStream() with directory
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file1 = rar_open(dirname(__FILE__).'/directories.rar');
$e = rar_entry_get($rar_file1, "emptydir");
$stream = $e->getStream();
var_dump($stream);
var_dump(feof($stream));
var_dump(fread($stream, 200));
var_dump(feof($stream));
echo "Done\n";
--EXPECTF--
resource(%d) of type (stream)
bool(false)
string(0) ""
bool(true)
Done

46
tests/024.phpt Normal file
View File

@@ -0,0 +1,46 @@
--TEST--
rar_open()/RarEntry::getStream() (headers level password)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
echo "--> should fail (no password):\n";
$rar_file1 = rar_open(dirname(__FILE__).'/encrypted_headers.rar');
$entries = rar_list($rar_file1);
echo "\n--> should fail (wrong password):\n";
$rar_file1 = rar_open(dirname(__FILE__).'/encrypted_headers.rar', 'wrongpassword');
$entries = rar_list($rar_file1);
echo "\n--> should work:\n";
$rar_file2 = rar_open(dirname(__FILE__).'/encrypted_headers.rar', 'samplepassword');
$entries = rar_list($rar_file2);
echo "Found " . count($entries) . " files.\n";
echo "Content of first one follows:\n";
//reset($entries)->extract(false, "./temp.txt");
$stream = reset($entries)->getStream();
var_dump($stream);
if ($stream !== FALSE) {
while (!feof($stream)) {
echo fread($stream, 128);
}
}
echo "\n";
echo "Done\n";
--EXPECTF--
--> should fail (no password):
Warning: rar_list(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
--> should fail (wrong password):
Warning: rar_list(): ERAR_BAD_DATA in %s on line %d
--> should work:
Found 2 files.
Content of first one follows:
resource(%d) of type (stream)
Encrypted file 1 contents.
Done

26
tests/025.phpt Normal file
View File

@@ -0,0 +1,26 @@
--TEST--
rar_open()/RarEntry::extract() (headers level password)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_file2 = rar_open(dirname(__FILE__).'/encrypted_headers.rar', 'samplepassword');
$entries = rar_list($rar_file2);
echo "Found " . count($entries) . " files.\n";
$tempfile = dirname(__FILE__).'/temp.txt';
@unlink($tempfile);
var_dump(reset($entries)->extract(false, $tempfile));
echo "Content of first one follows:\n";
echo file_get_contents($tempfile);
$stream = reset($entries)->getStream();
@unlink($tempfile);
echo "\n";
echo "Done\n";
--EXPECTF--
Found 2 files.
bool(true)
Content of first one follows:
Encrypted file 1 contents.
Done

52
tests/026.phpt Normal file
View File

@@ -0,0 +1,52 @@
--TEST--
RarEntry::getStream() (file level password)
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
echo "--> should fail (no password):\n";
$rar_file1 = rar_open(dirname(__FILE__).'/encrypted_only_files.rar');
$entries = rar_list($rar_file1);
var_dump(count($entries));
var_dump($entries[0]->getStream());
echo "\n";
echo "--> success (password is the same as the one given on rar_open):\n";
$rar_file2 = rar_open(dirname(__FILE__).'/encrypted_only_files.rar', 'samplepassword');
$entries = rar_list($rar_file2);
echo stream_get_contents($entries[0]->getStream());
echo "\n\n";
echo "--> should give incorrect data (password of 2nd file different from the one given on rar_open):\n";
echo rawurlencode(stream_get_contents($entries[1]->getStream()));
echo "\n\n";
echo "--> should give correct data (password of 2nd file is specified):\n";
echo stream_get_contents($entries[1]->getStream('samplepassword2'));
echo "\n\n";
echo "--> success (password is the same as the one given on rar_open, which shouldn't have been forgotten):\n";
echo stream_get_contents($entries[0]->getStream());
echo "\n\n";
echo "Done\n";
--EXPECTF--
--> should fail (no password):
int(2)
Warning: RarEntry::getStream(): ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
bool(false)
--> success (password is the same as the one given on rar_open):
Encrypted file 1 contents.
--> should give incorrect data (password of 2nd file different from the one given on rar_open):
t%09%A6%2B%0D%1B%F6%815%5E%E7%EC%C0%0BF%5EH%3A%C0%0D%815%5E%E7%EC%C0
--> should give correct data (password of 2nd file is specified):
Encrypted file 1 contents.
--> success (password is the same as the one given on rar_open, which shouldn't have been forgotten):
Encrypted file 1 contents.
Done

54
tests/027.phpt Normal file
View File

@@ -0,0 +1,54 @@
--TEST--
RarEntry::getStream() with Linux directories and links
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar = rar_open(dirname(__FILE__) . "/dirlink_unix.rar");
echo "\nDirectory\n";
$e = rar_entry_get($rar, "nopermdir");
echo $e."\n";
echo "perms: " . decoct($e->getAttr() & 0x1FF) . "\n"; //no read/write/execute perms
echo "win directory bit: " . (($e->getAttr() & RarEntry::ATTRIBUTE_WIN_DIRECTORY) != 0) ."\n";
echo "unix directory attr: " . (($e->getAttr() & RarEntry::ATTRIBUTE_UNIX_FINAL_QUARTET)
== RarEntry::ATTRIBUTE_UNIX_DIRECTORY) ."\n";
echo "unix symlink attr: " . (($e->getAttr() & RarEntry::ATTRIBUTE_UNIX_FINAL_QUARTET)
== RarEntry::ATTRIBUTE_UNIX_SYM_LINK) ."\n";
$stream = $e->getStream();
$cont = stream_get_contents($stream);
echo "$cont (strlen() " . strlen($cont) . ")\n";
echo "\nLink\n";
$e = rar_entry_get($rar, "link");
echo $e."\n";
echo "perms: " . decoct($e->getAttr() & 0x1FF) . "\n";
echo "win directory bit: " . (($e->getAttr() & RarEntry::ATTRIBUTE_WIN_DIRECTORY) != 0) ."\n"; //coincidence
echo "unix directory attr: " . (($e->getAttr() & RarEntry::ATTRIBUTE_UNIX_FINAL_QUARTET)
== RarEntry::ATTRIBUTE_UNIX_DIRECTORY) ."\n";
echo "unix symlink attr: " . (($e->getAttr() & RarEntry::ATTRIBUTE_UNIX_FINAL_QUARTET)
== RarEntry::ATTRIBUTE_UNIX_SYM_LINK) ."\n";
$stream = $e->getStream();
$cont = stream_get_contents($stream);
echo "$cont (strlen() " . strlen($cont) . ")\n"; //varies on windows and linux
echo "Done\n";
--EXPECTF--
Directory
RarEntry for directory "nopermdir" (0)
perms: 0
win directory bit:
unix directory attr: 1
unix symlink attr:
(strlen() 0)
Link
RarEntry for file "link" (43e55b49)
perms: 777
win directory bit: 1
unix directory attr:
unix symlink attr: 1
%s
Done

14
tests/028.phpt Normal file
View File

@@ -0,0 +1,14 @@
--TEST--
RarArchive::open() basic test
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$arch = RarArchive::open(dirname(__FILE__) . "/dirlink_unix.rar");
var_dump(get_class($arch));
echo "Done\n";
--EXPECTF--
string(10) "RarArchive"
Done

21
tests/029.phpt Normal file
View File

@@ -0,0 +1,21 @@
--TEST--
RarArchive::getEntries() basic test
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$arch = RarArchive::open(dirname(__FILE__) . "/dirlink_unix.rar");
foreach ($arch->getEntries() as $e) {
echo $e . "\n";
}
echo "Done\n";
--EXPECTF--
RarEntry for file "emptydir%clink" (36ac99f1)
RarEntry for file "file" (b95e8411)
RarEntry for file "link" (43e55b49)
RarEntry for directory "emptydir" (0)
RarEntry for directory "nopermdir" (0)
RarEntry for directory "setuiddir" (0)
RarEntry for directory "stickydir" (0)
Done

14
tests/030.phpt Normal file
View File

@@ -0,0 +1,14 @@
--TEST--
RarArchive::getEntry() basic test
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_arch = RarArchive::open(dirname(__FILE__) . '/solid.rar');
$rar_entry = $rar_arch->getEntry('tese.txt');
echo $rar_entry;
echo "\n";
echo "Done\n";
--EXPECTF--
RarEntry for file "tese.txt" (23b93a7a)
Done

13
tests/031.phpt Normal file
View File

@@ -0,0 +1,13 @@
--TEST--
RarArchive::getComment() basic test
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rar_arch = RarArchive::open(dirname(__FILE__) . '/commented.rar');
echo $rar_arch->getComment();
echo "\n";
echo "Done\n";
--EXPECTF--
This is the comment of the file commented.rar.
Done

16
tests/032.phpt Normal file
View File

@@ -0,0 +1,16 @@
--TEST--
RarArchive traversal with multi-part archive
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rarF = RarArchive::open(dirname(__FILE__) . '/multi.part1.rar');
foreach ($rarF as $k => $rarE) {
echo "$k. $rarE\n";
}
echo "Done\n";
--EXPECTF--
0. RarEntry for file "file1.txt" (52b28202)
1. RarEntry for file "file2.txt" (f2c79881)
2. RarEntry for file "file3.txt" (bcbce32e)
Done

24
tests/033.phpt Normal file
View File

@@ -0,0 +1,24 @@
--TEST--
rar_solid_is() basic test
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$arch1 = RarArchive::open(dirname(__FILE__) . "/store_method.rar");
$arch2 = RarArchive::open(dirname(__FILE__) . "/solid.rar");
echo "$arch1: " . ($arch1->isSolid()?'yes':'no') ."\n";
echo "$arch2: " . (rar_solid_is($arch2)?'yes':'no') . "\n";
$arch2->close();
var_dump(rar_solid_is($arch2));
echo "\n";
echo "Done.\n";
--EXPECTF--
RAR Archive "%sstore_method.rar": no
RAR Archive "%ssolid.rar": yes
Warning: rar_solid_is(): The archive is already closed in %s on line %d
bool(false)
Done.

16
tests/034.phpt Normal file
View File

@@ -0,0 +1,16 @@
--TEST--
RarException::(set/is)UsingExceptions() test
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
echo "Initial state: " . (RarException::isUsingExceptions()?'yes':'no').".\n";
RarException::setUsingExceptions(true);
echo "State change done.\n";
echo "Final state: " . (RarException::isUsingExceptions()?'yes':'no').".\n";
echo "Done.\n";
--EXPECTF--
Initial state: no.
State change done.
Final state: yes.
Done.

19
tests/035.phpt Normal file
View File

@@ -0,0 +1,19 @@
--TEST--
rar_entry_get() non-existent file with exceptions
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
RarException::setUsingExceptions(true);
$arch = RarArchive::open(dirname(__FILE__) . "/latest_winrar.rar");
try {
$arch->getEntry('nonexistentfile.txt');
} catch (RarException $re) {
echo "Message: " . $re->getMessage()."\n";
echo "Code: " . $re->getCode() ."\n";
}
echo "Done.\n";
--EXPECTF--
Message: cannot find file "nonexistentfile.txt" in Rar archive "%slatest_winrar.rar"
Code: -1
Done.

18
tests/036.phpt Normal file
View File

@@ -0,0 +1,18 @@
--TEST--
rar_open() non-existent archive with exceptions
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
RarException::setUsingExceptions(true);
try {
$arch = RarArchive::open(dirname(__FILE__) . "/nonexistentarchive.rar");
} catch (RarException $re) {
echo "Message: " . $re->getMessage()."\n";
echo "Code: " . $re->getCode() ."\n";
}
echo "Done.\n";
--EXPECTF--
Message: unRAR internal error: Failed to open %snonexistentarchive.rar: ERAR_EOPEN (file open error)
Code: 15
Done.

24
tests/037.phpt Normal file
View File

@@ -0,0 +1,24 @@
--TEST--
RarEntry::getStream(), password not given, with exceptions
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
RarException::setUsingExceptions(true);
echo "--> should fail (no password):\n";
$rar_file1 = rar_open(dirname(__FILE__).'/encrypted_only_files.rar');
$entries = rar_list($rar_file1);
var_dump(count($entries));
try {
var_dump($entries[0]->getStream());
} catch (RarException $re) {
echo "Message: " . $re->getMessage()."\n";
echo "Code: " . $re->getCode() ."\n";
}
echo "Done.\n";
--EXPECTF--
--> should fail (no password):
int(2)
Message: unRAR internal error: ERAR_MISSING_PASSWORD (password needed but not specified)
Code: 22
Done.

15
tests/038.phpt Normal file
View File

@@ -0,0 +1,15 @@
--TEST--
RarArchive get iterator on closed file
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rarF = RarArchive::open(dirname(__FILE__) . '/latest_winrar.rar');
$rarF->close();
foreach ($rarF as $k => $rarE) {
echo "$k. $rarE\n";
unset($rarE);
}
echo "Done.\n";
--EXPECTF--
Fatal error: main(): The archive is already closed, cannot give an iterator in %s on line %d%A

15
tests/039.phpt Normal file
View File

@@ -0,0 +1,15 @@
--TEST--
Access RAR archive with missing volumes
--SKIPIF--
<?php if(!extension_loaded("rar")) print "skip"; ?>
--FILE--
<?php
$rarF = RarArchive::open(dirname(__FILE__) . '/multi_broken.part1.rar');
var_dump(rar_list($rarF));
echo "Done.\n";
--EXPECTF--
Warning: rar_list(): Volume %smulti_broken.part2.rar was not found in %s on line %d
Warning: rar_list(): ERAR_EOPEN (file open error) in %s on line %d
bool(false)
Done.

26
tests/040.phpt Normal file
View File

@@ -0,0 +1,26 @@
--TEST--
RarEntry::getUnpackedSize() on platforms with 32-bit longs
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platforms only");
--FILE--
<?php
$fn1 = dirname(__FILE__) . '/sparsefiles_rar.rar';
$fn2 = dirname(__FILE__) . '/sparsefiles.tmp.rar';
$rarF = RarArchive::open($fn1);
$t = $rarF->getEntries();
reset($t)->extract(false, $fn2);
$rarF2 = RarArchive::open($fn2);
$t = $rarF2->getEntries();
var_dump($t[0]->getUnpackedSize());
var_dump($t[1]->getUnpackedSize());
echo "Done.\n";
--CLEAN--
<?php
$fn2 = dirname(__FILE__) . '/sparsefiles.tmp.rar';
@unlink($fn2);
--EXPECTF--
int(2147483647)
int(2147483647)
Done.

26
tests/041.phpt Normal file
View File

@@ -0,0 +1,26 @@
--TEST--
RarEntry::getUnpackedSize() on platforms with 64-bit longs
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platforms only");
--FILE--
<?php
$fn1 = dirname(__FILE__) . '/sparsefiles_rar.rar';
$fn2 = dirname(__FILE__) . '/sparsefiles.tmp.rar';
$rarF = RarArchive::open($fn1);
$t = $rarF->getEntries();
reset($t)->extract(false, $fn2);
$rarF2 = RarArchive::open($fn2);
$t = $rarF2->getEntries();
var_dump($t[0]->getUnpackedSize());
var_dump($t[1]->getUnpackedSize());
echo "Done.\n";
--CLEAN--
<?php
$fn2 = dirname(__FILE__) . '/sparsefiles.tmp.rar';
@unlink($fn2);
--EXPECTF--
int(2621440000)
int(5368709120)
Done.

38
tests/042.phpt Normal file
View File

@@ -0,0 +1,38 @@
--TEST--
rar_open() with volume find callback basic test
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--FILE--
<?php
chdir(dirname(__FILE__));
function volume_callback($vol) {
if (strpos($vol, '_fail') !== false)
$ret = basename(str_replace('_fail', '', $vol));
elseif (strpos($vol, '_broken') !== false)
$ret = basename(str_replace('_broken', '_fail', $vol));
else
$ret = null;
echo "Not found:\n\t$vol\nReplacing with:\n\t$ret\n";
return $ret;
}
$fn = dirname(__FILE__) . '/multi_broken.part1.rar';
$rar = RarArchive::open($fn, null, 'volume_callback');
foreach ($rar as $e) {
echo "Entry: $e.\n";
}
echo "Done.\n";
--EXPECTF--
Not found:
%smulti_broken.part2.rar
Replacing with:
multi_fail.part2.rar
Not found:
%smulti_fail.part2.rar
Replacing with:
multi.part2.rar
Entry: RarEntry for file "file1.txt" (52b28202).
Entry: RarEntry for file "file2.txt" (f2c79881).
Entry: RarEntry for file "file3.txt" (bcbce32e).
Done.

47
tests/043.phpt Normal file
View File

@@ -0,0 +1,47 @@
--TEST--
rar_open() with volume find (callback variants 1)
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--FILE--
<?php
class A {
public static function resolve($vol) {
if (preg_match('/_broken/', $vol))
return str_replace('_broken', '', $vol);
else
return null;
}
public static function resolveStatic($vol) {
echo "A::resolveStatic()\n";
return self::resolve($vol);
}
public function resolveInstance($vol) {
echo "A::resolveInstance()\n";
return self::resolve($vol);
}
}
$fn = dirname(__FILE__) . '/multi_broken.part1.rar';
$rar = RarArchive::open($fn, null, "A::resolveStatic");
$rar->getEntries();
$rar = RarArchive::open($fn, null, array("A", "resolveStatic"));
$rar->getEntries();
$rar = RarArchive::open($fn, null, array(new A(), "resolveInstance"));
$rar->getEntries();
function testA() {
global $fn;
$obj = new A();
return RarArchive::open($fn, null, array($obj, "resolveInstance"));
}
$rar = testA();
$rar->getEntries();
echo "Done.\n";
--EXPECTF--
A::resolveStatic()
A::resolveStatic()
A::resolveInstance()
A::resolveInstance()
Done.

45
tests/044.phpt Normal file
View File

@@ -0,0 +1,45 @@
--TEST--
rar_open() with volume find (callback variants 2)
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
if(!defined('PHP_VERSION_ID') || PHP_VERSION_ID<50300) die("skip");
--FILE--
<?php
class A {
public static function resolve($vol) {
if (preg_match('/_broken/', $vol))
return str_replace('_broken', '', $vol);
else
return null;
}
public function __invoke($vol) {
echo "A::__invoke()\n";
return self::resolve($vol);
}
}
$fn = dirname(__FILE__) . '/multi_broken.part1.rar';
$f = function ($vol) {
echo "Closure\n";
return A::resolve($vol);
};
$rar = RarArchive::open($fn, null, new A());
$rar->getEntries();
$rar = RarArchive::open($fn, null, $f);
$rar->getEntries();
$f2 = function ($vol) {
echo "Closure (2)\n";
return A::resolve($vol);
};
$rar = RarArchive::open($fn, null, $f2);
unset($f2);
$rar->getEntries();
echo "Done.\n";
--EXPECTF--
A::__invoke()
Closure
Closure (2)
Done.

113
tests/045.phpt Normal file
View File

@@ -0,0 +1,113 @@
--TEST--
rar_open() with invalid volume callback
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--FILE--
<?php
require __DIR__ . "/php8compat.php.inc";
class A {
public static function resolve($vol) {
if (preg_match('/_broken/', $vol))
return str_replace('_broken', '', $vol);
else
return null;
}
public function resolveInstance($vol) {
echo "A::resolveInstance()\n";
return self::resolve($vol);
}
}
$fn = dirname(__FILE__) . '/multi_broken.part1.rar';
echo "\nNot given a callback:\n";
$rar = RarArchive::open($fn, null, new Exception());
echo "\nGiven static callback for instance method (test IS_CALLABLE_STRICT):\n";
$rar = RarArchive::open($fn, null, "A::resolveInstance");
var_dump($rar);
echo "\nGiven callback that takes more arguments:\n";
$rar = RarArchive::open($fn, null, 'strpos');
argerr(function() use ($rar) {
$rar->getEntries();
});
echo "\nGiven callback that takes another kind of arguments:\n";
$rar = RarArchive::open($fn, null, 'array_keys');
argerr(function() use ($rar) {
$rar->getEntries();
});
echo "\nGiven callback that returns another kind of arguments:\n";
function testA($vol) { return true; }
$rar = RarArchive::open($fn, null, 'testA');
$rar->getEntries();
echo "\nGiven callback that throws Exception:\n";
function testB($vol) { throw new Exception(); }
$rar = RarArchive::open($fn, null, 'testB');
try {
$rar->getEntries();
die("should have thrown exception.");
} catch (Exception $e) {
echo "OK, threw exception.\n";
}
echo "Done.\n";
--EXPECTF_DYNAMIC--
Not given a callback:
Warning: RarArchive::open(): Expected the third argument, if provided, to be a valid callback in %s on line %d
Given static callback for instance method (test IS_CALLABLE_STRICT):
Warning: RarArchive::open(): Expected the third argument, if provided, to be a valid callback in %s on line %d
bool(false)
Given callback that takes more arguments:
<?php if (PHP_VERSION_ID >= 80000) { ?>
Warning: RarArchive::getEntries(): Failure to call volume find callback in %s on line %d
<?php } ?>
<?php if (PHP_VERSION_ID >= 80000) { ?>
Warning: RarArchive::getEntries(): ERAR_EOPEN (file open error) in %s on line %d
Warning: strpos() expects at least %d parameters, 1 given in %s on line %d
<?php } else { ?>
Warning: strpos() expects at least %d parameters, 1 given in %s on line %d
Warning: RarArchive::getEntries(): ERAR_EOPEN (file open error) in %s on line %d
<?php } ?>
Given callback that takes another kind of arguments:
<?php if (PHP_VERSION_ID >= 80000) { ?>
Warning: RarArchive::getEntries(): Failure to call volume find callback in %s on line %d
Warning: RarArchive::getEntries(): ERAR_EOPEN (file open error) in %s on line %d
Warning: array_keys() expects parameter 1 to be array, string given in %s on line %d
<?php } else { ?>
Warning: array_keys() expects parameter 1 to be array, string given in %s on line %d
Warning: RarArchive::getEntries(): ERAR_EOPEN (file open error) in %s on line %d
<?php } ?>
Given callback that returns another kind of arguments:
Warning: RarArchive::getEntries(): Wrong type returned by volume find callback, expected string or NULL in %s on line %d
Warning: RarArchive::getEntries(): ERAR_EOPEN (file open error) in %s on line %d
Given callback that throws Exception:
Warning: RarArchive::getEntries(): Failure to call volume find callback in %s on line %d
Warning: RarArchive::getEntries(): ERAR_EOPEN (file open error) in %s on line %d
OK, threw exception.
Done.

41
tests/046.phpt Normal file
View File

@@ -0,0 +1,41 @@
--TEST--
RarEntry::getStream() function (broken set fixed with volume callback)
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
if(PHP_INT_SIZE < 8) die("skip 32-bit PHP not supported");
?>
--FILE--
<?php
function resolve($vol) {
if (preg_match('/_broken/', $vol))
return str_replace('_broken', '', $vol);
else
return null;
}
function int32_to_hex($value) {
$value &= 0xffffffff;
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
}
$rar_file1 = rar_open(dirname(__FILE__).'/multi_broken.part1.rar', null, 'resolve');
foreach ($rar_file1 as $e) {
$stream = $e->getStream();
echo $e->getName().": ";
$a = "";
while (is_resource($stream) && !feof($stream)) {
$a .= fread($stream, 8192);
}
echo strlen($a)." bytes, CRC ";
echo int32_to_hex(crc32($a))."\n\n"; //you can confirm they're equal to those given by $e->getCrc()
}
echo "Done\n";
?>
--EXPECTF--
file1.txt: 18 bytes, CRC 52B28202
file2.txt: 17704 bytes, CRC F2C79881
file3.txt: 18 bytes, CRC BCBCE32E
Done

44
tests/047.phpt Normal file
View File

@@ -0,0 +1,44 @@
--TEST--
RarEntry::extract() function (broken set fixed with volume callback)
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
if(PHP_INT_SIZE < 8) die("skip 32-bit PHP not supported");
?>
--FILE--
<?php
function resolve($vol) {
if (preg_match('/_broken/', $vol))
return str_replace('_broken', '', $vol);
else
return null;
}
function int32_to_hex($value) {
$value &= 0xffffffff;
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
}
echo "Fail:\n";
$rar_file1 = rar_open(dirname(__FILE__).'/multi_broken.part1.rar');
$entry = $rar_file1->getEntry('file2.txt');
echo "\nSuccess:\n";
$rar_file1 = rar_open(dirname(__FILE__).'/multi_broken.part1.rar', null, 'resolve');
$entry = $rar_file1->getEntry('file2.txt');
$entry->extract(null, dirname(__FILE__) . "/temp_file2.txt");
echo int32_to_hex(crc32(file_get_contents(dirname(__FILE__) . "/temp_file2.txt")));
echo "\n";
echo "Done\n";
?>
--CLEAN--
<?php
@unlink(dirname(__FILE__) . "/temp_file2.txt");
--EXPECTF--
Fail:
Warning: RarArchive::getEntry(): Volume %smulti_broken.part2.rar was not found in %s on line %d
Warning: RarArchive::getEntry(): ERAR_EOPEN (file open error) in %s on line %d
Success:
F2C79881
Done

26
tests/048.phpt Normal file
View File

@@ -0,0 +1,26 @@
--TEST--
RarArchive::open() volume callback long return (case MAXPATHLEN <= NM)
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
if (!defined("PHP_MAXPATHLEN"))
define("PHP_MAXPATHLEN", RAR_MAXPATHLEN);
if (!(PHP_MAXPATHLEN <= 1024))
die("skip; this test is for systems where MAXPATHLEN <= 1024");
--FILE--
<?php
if (!defined("PHP_MAXPATHLEN"))
define("PHP_MAXPATHLEN", RAR_MAXPATHLEN);
$fn = dirname(__FILE__) . '/multi_broken.part1.rar';
function testA($vol) { if ($vol[0] != 'a') return str_repeat("a", PHP_MAXPATHLEN); }
$rar = RarArchive::open($fn, null, 'testA');
$rar->getEntries();
echo "Done.\n";
--EXPECTF--
Warning: RarArchive::getEntries(): Cound not expand filename aaaa%s in %s on line %d
Warning: RarArchive::getEntries(): ERAR_EOPEN (file open error) in %s on line %d
Done.

31
tests/049.phpt Normal file
View File

@@ -0,0 +1,31 @@
--TEST--
RarArchive::open() volume callback long return (case MAXPATHLEN > MAXPATHSIZE)
--SKIPIF--
<?php
define('MAXPATHSIZE', 0x10000);
if(!extension_loaded("rar")) die("skip");
if (!defined("PHP_MAXPATHLEN"))
define("PHP_MAXPATHLEN", RAR_MAXPATHLEN);
if (!(PHP_MAXPATHLEN > MAXPATHSIZE))
die("skip test is for systems where MAXPATHLEN > 2048");
$rp = dirname(__FILE__) . "/" . str_repeat("a", MAXPATHSIZE);
if (strlen(dirname(__FILE__) > PHP_MAXPATHLEN - 1))
die("skip current directory is too deep.");
--FILE--
<?php
if (!defined("PHP_MAXPATHLEN"))
define("PHP_MAXPATHLEN", RAR_MAXPATHLEN);
chdir(dirname(__FILE__));
$fn = dirname(__FILE__) . '/multi_broken.part1.rar';
function testA($vol) { if ($vol[0] != 'a') return str_repeat("a", MAXPATHSIZE); }
$rar = RarArchive::open($fn, null, 'testA');
$rar->getEntries();
echo "Done.\n";
--EXPECTF--
Warning: RarArchive::getEntries(): Resolved path is too big for the unRAR library in %s on line %d
Warning: RarArchive::getEntries(): ERAR_EOPEN (file open error) in %s on line %d
Done.

16
tests/050.phpt Normal file
View File

@@ -0,0 +1,16 @@
--TEST--
Stream wrapper basic test
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--FILE--
<?php
$stream = fopen("rar://" .
dirname(__FILE__) . '/latest_winrar.rar' .
"#1.txt", "r");
var_dump(stream_get_contents($stream));
echo "Done.\n";
--EXPECTF--
string(5) "11111"
Done.

62
tests/051.phpt Normal file
View File

@@ -0,0 +1,62 @@
--TEST--
Stream wrapper relative path test
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--CLEAN--
<?php
unlink(dirname(__FILE__) . '/temp/tmp.rar');
rmdir(dirname(__FILE__) . "/temp");
--FILE--
<?php
mkdir(dirname(__FILE__) . "/temp");
chdir(dirname(__FILE__) . "/temp");
echo "Test relative to working dir:\n";
$stream = fopen("rar://" .
'../latest_winrar.rar' .
"#1.txt", "r");
var_dump(stream_get_contents($stream));
echo "\nTest with include path:\n";
copy(dirname(__FILE__) . '/latest_winrar.rar',
dirname(__FILE__) . '/temp/tmp.rar');
chdir(dirname(__FILE__));
//now with include
echo "Should fail (not in include):\n";
$stream = fopen("rar://" .
'tmp.rar' .
"#1.txt", "r");
echo "\nShould fail (include unused):\n";
set_include_path(dirname(__FILE__). '/temp');
$stream = fopen("rar://" .
'tmp.rar' .
"#1.txt", "r");
echo "\nShould succeed:\n";
$stream = fopen("rar://" .
'tmp.rar' .
"#1.txt", "r", true);
var_dump(stream_get_contents($stream));
echo "Done.\n";
--EXPECTF--
Test relative to working dir:
string(5) "11111"
Test with include path:
Should fail (not in include):
Warning: fopen(rar://tmp.rar#1.txt): %cailed to open stream: Error opening RAR archive %stmp.rar: ERAR_EOPEN (file open error) in %s on line %d
Should fail (include unused):
Warning: fopen(rar://tmp.rar#1.txt): %cailed to open stream: Error opening RAR archive %stmp.rar: ERAR_EOPEN (file open error) in %s on line %d
Should succeed:
string(5) "11111"
Done.

28
tests/052.phpt Normal file
View File

@@ -0,0 +1,28 @@
--TEST--
Stream wrapper archive/file not found
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--FILE--
<?php
echo "Archive not found :\n";
$stream = fopen("rar://" .
dirname(__FILE__) . "/not_found.rar" .
"#1.txt", "r");
echo "\nFile not found :\n";
$stream = fopen("rar://" .
dirname(__FILE__) . "/latest_winrar.rar" .
"#not_found.txt", "r");
echo "Done.\n";
--EXPECTF--
Archive not found :
Warning: fopen(rar://%snot_found.rar#1.txt): %cailed to open stream: Error opening RAR archive %snot_found.rar: ERAR_EOPEN (file open error) in %s on line %d
File not found :
Warning: fopen(rar://%slatest_winrar.rar#not_found.txt): %cailed to open stream: Can't file not_found.txt in RAR archive %s on line %d
Done.

47
tests/053.phpt Normal file
View File

@@ -0,0 +1,47 @@
--TEST--
Stream wrapper malformed url
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--FILE--
<?php
echo "Test empty:\n";
$stream = fopen("rar://", "r");
echo "\nTest no fragment:\n";
$stream = fopen("rar://file.rar", "r");
echo "\nTest empty fragment:\n";
$stream = fopen("rar://file.rar#", "r");
echo "\nTest no path:\n";
$stream = fopen("rar://#frag", "r");
echo "\nTest no path and empty fragment:\n";
$stream = fopen("rar://#", "r");
echo "Done.\n";
--EXPECTF--
Test empty:
Warning: fopen(rar://): %cailed to open stream: The url must contain a path and a non-empty fragment; it must be in the form "rar://<urlencoded path to RAR archive>[*]#<urlencoded entry name>" in %s on line %d
Test no fragment:
Warning: fopen(rar://file.rar): %cailed to open stream: The url must contain a path and a non-empty fragment; it must be in the form "rar://<urlencoded path to RAR archive>[*]#<urlencoded entry name>" in %s on line %d
Test empty fragment:
Warning: fopen(rar://file.rar#): %cailed to open stream: The url must contain a path and a non-empty fragment; it must be in the form "rar://<urlencoded path to RAR archive>[*]#<urlencoded entry name>" in %s on line %d
Test no path:
Warning: fopen(rar://#frag): %cailed to open stream: The url must contain a path and a non-empty fragment; it must be in the form "rar://<urlencoded path to RAR archive>[*]#<urlencoded entry name>" in %s on line %d
Test no path and empty fragment:
Warning: fopen(rar://#): %cailed to open stream: The url must contain a path and a non-empty fragment; it must be in the form "rar://<urlencoded path to RAR archive>[*]#<urlencoded entry name>" in %s on line %d
Done.

79
tests/054.phpt Normal file
View File

@@ -0,0 +1,79 @@
--TEST--
Stream wrapper with header or file level passwords
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--FILE--
<?php
echo "Headers: should not work (no password):\n";
$stream = fopen("rar://" .
dirname(__FILE__) . '/encrypted_headers.rar' .
"#encfile1.txt", "r");
echo "\nHeaders: should not work (password given was file_password):\n";
$stream = fopen("rar://" .
dirname(__FILE__) . '/encrypted_headers.rar' .
"#encfile1.txt", "r", false,
stream_context_create(array('rar'=>array('file_password'=>'samplepassword'))));
echo "\nHeaders: should work (password given was open_password):\n";
$stream = fopen("rar://" .
dirname(__FILE__) . '/encrypted_headers.rar' .
"#encfile1.txt", "r", false,
stream_context_create(array('rar'=>array('open_password'=>'samplepassword'))));
var_dump(stream_get_contents($stream));
//////////////////////
echo "\n\nFiles: should not work (no password):\n";
$stream = fopen("rar://" .
dirname(__FILE__) . '/encrypted_only_files.rar' .
"#encfile1.txt", "r");
echo "\nFiles: should not work (password given was open_password):\n";
$stream = fopen("rar://" .
dirname(__FILE__) . '/encrypted_only_files.rar' .
"#encfile1.txt", "r", false,
stream_context_create(array('rar'=>array('open_password'=>'samplepassword'))));
echo "\nFiles: should work (password given was file_password):\n";
$stream = fopen("rar://" .
dirname(__FILE__) . '/encrypted_only_files.rar' .
"#encfile1.txt", "r", false,
stream_context_create(array('rar'=>array('file_password'=>'samplepassword'))));
var_dump(stream_get_contents($stream));
echo "\nDone.\n";
--EXPECTF--
Headers: should not work (no password):
Warning: fopen(rar://%sencrypted_headers.rar#encfile1.txt): %cailed to open stream: Error opening RAR archive %sencrypted_headers.rar: ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
Headers: should not work (password given was file_password):
Warning: fopen(rar://%sencrypted_headers.rar#encfile1.txt): %cailed to open stream: Error opening RAR archive %sencrypted_headers.rar: ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
Headers: should work (password given was open_password):
string(26) "Encrypted file 1 contents."
Files: should not work (no password):
Warning: fopen(rar://%sencrypted_only_files.rar#encfile1.txt): %cailed to open stream: Error opening file encfile1.txt inside RAR archive %sencrypted_only_files.rar: ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
Files: should not work (password given was open_password):
Warning: fopen(rar://%sencrypted_only_files.rar#encfile1.txt): %cailed to open stream: Error opening file encfile1.txt inside RAR archive %sencrypted_only_files.rar: ERAR_MISSING_PASSWORD (password needed but not specified) in %s on line %d
Files: should work (password given was file_password):
string(26) "Encrypted file 1 contents."
Done.

31
tests/055.phpt Normal file
View File

@@ -0,0 +1,31 @@
--TEST--
Stream wrapper with volume find callback
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
if(PHP_INT_SIZE < 8) die("skip 32-bit PHP not supported");
--FILE--
<?php
function resolve($vol) {
if (preg_match('/_broken/', $vol))
return str_replace('_broken', '', $vol);
else
return null;
}
function int32_to_hex($value) {
$value &= 0xffffffff;
return str_pad(strtoupper(dechex($value)), 8, "0", STR_PAD_LEFT);
}
$stream = fopen("rar://" .
dirname(__FILE__) . '/multi_broken.part1.rar' .
"#file2.txt", "r", false,
stream_context_create(array('rar'=>array('volume_callback'=>'resolve'))));
$a = stream_get_contents($stream);
echo strlen($a)." bytes, CRC ";
echo int32_to_hex(crc32($a))."\n\n"; //you can confirm they're equal to those given by $e->getCrc()
echo "Done.\n";
--EXPECTF--
17704 bytes, CRC F2C79881
Done.

40
tests/056.phpt Normal file
View File

@@ -0,0 +1,40 @@
--TEST--
RAR file stream stat
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--ENV--
TZ=Asia/Tokyo
--FILE--
<?php
umask(0);
$stream = fopen("rar://" .
dirname(__FILE__) . '/latest_winrar.rar' .
"#1.txt", "r");
$r = array_slice(fstat($stream), 13);
if (PHP_OS == 'WINNT') {
// we don't return the correct value on windows
$r['mtime'] = 1086948439;
}
print_r($r);
echo "Done.\n";
--EXPECTF--
Array
(
[dev] => 0
[ino] => 0
[mode] => 33206
[nlink] => 1
[uid] => 0
[gid] => 0
[rdev] => 0
[size] => 5
[atime] => 0
[mtime] => 1086948439
[ctime] => 0
[blksize] => %s
[blocks] => %s
)
Done.

21
tests/057.phpt Normal file
View File

@@ -0,0 +1,21 @@
--TEST--
RAR file stream stat consistency with url stat
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--FILE--
<?php
$u = "rar://" .
dirname(__FILE__) . '/latest_winrar.rar' .
"#1.txt";
$stream = fopen($u, "r");
$fs = (fstat($stream));
$us = stat($u);
var_dump($fs == $us);
echo "Done.\n";
--EXPECTF--
bool(true)
Done.

24
tests/058.phpt Normal file
View File

@@ -0,0 +1,24 @@
--TEST--
RAR file stream stat applied to directory consistency with url stat
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--FILE--
<?php
$u = "rar://" .
dirname(__FILE__) . '/dirlink_unix.rar' .
"#emptydir";
$stream = fopen($u, "r");
$fs = (fstat($stream));
$us = stat($u);
var_dump($fs == $us);
var_dump(is_dir($u));
echo "Done.\n";
--EXPECTF--
bool(true)
bool(true)
Done.

136
tests/059.phpt Normal file
View File

@@ -0,0 +1,136 @@
--TEST--
url stat test
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--ENV--
TZ=Europe/Lisbon
--FILE--
<?php
umask(0);
$inex_rar = "rar://" .
dirname(__FILE__) . '/not_found.rar' .
"#emptydir";
echo "RAR not found:\n";
var_dump(stat($inex_rar));
$inex_entry = "rar://" .
dirname(__FILE__) . '/dirlink_unix.rar' .
"#inexistent entry";
echo "\nRAR entry not found:\n";
var_dump(stat($inex_entry));
$root1 = "rar://" .
dirname(__FILE__) . '/dirlink_unix.rar';
echo "\nRAR root:\n";
$statr1 = stat($root1);
print_r(array_slice($statr1, 13));
echo "\nRAR root is dir:\n";
var_dump(is_dir($root1));
$root2 = "rar://" .
dirname(__FILE__) . '/dirlink_unix.rar#';
echo "\nRAR root variant 2 matches:\n";
var_dump(stat($root2) == $statr1);
$root3 = "rar://" .
dirname(__FILE__) . '/dirlink_unix.rar#/';
echo "\nRAR root variant 3 matches:\n";
var_dump(stat($root3) == $statr1);
$file = "rar://" .
dirname(__FILE__) . '/dirlink_unix.rar' .
"#file";
echo "\nRegular file:\n";
print_r(array_slice(stat($file), 13));
$dir = "rar://" .
dirname(__FILE__) . '/dirlink_unix.rar' .
"#emptydir";
echo "\nRegular file:\n";
print_r(array_slice(stat($dir), 13));
echo "Done.\n";
--EXPECTF--
RAR not found:
Warning: stat(): Failed to open %snot_found.rar: ERAR_EOPEN (file open error) in %s on line %d
Warning: stat(): stat failed for rar://%s/not_found.rar#emptydir in %s on line %d
bool(false)
RAR entry not found:
Warning: stat(): Found no entry inexistent entry in archive %sdirlink_unix.rar in %s on line %d
Warning: stat(): stat failed for rar://%s/dirlink_unix.rar#inexistent entry in %s on line %d
bool(false)
RAR root:
Array
(
[dev] => 0
[ino] => 0
[mode] => 16895
[nlink] => 1
[uid] => 0
[gid] => 0
[rdev] => 0
[size] => 0
[atime] => 0
[mtime] => 312768000
[ctime] => 0
[blksize] => %s
[blocks] => %s
)
RAR root is dir:
bool(true)
RAR root variant 2 matches:
bool(true)
RAR root variant 3 matches:
bool(true)
Regular file:
Array
(
[dev] => 0
[ino] => 0
[mode] => 33188
[nlink] => 1
[uid] => 0
[gid] => 0
[rdev] => 0
[size] => 8
[atime] => 0
[mtime] => 1259625512
[ctime] => 0
[blksize] => %s
[blocks] => %s
)
Regular file:
Array
(
[dev] => 0
[ino] => 0
[mode] => 16877
[nlink] => 1
[uid] => 0
[gid] => 0
[rdev] => 0
[size] => 0
[atime] => 0
[mtime] => 1259625807
[ctime] => 0
[blksize] => %s
[blocks] => %s
)
Done.

61
tests/060.phpt Normal file
View File

@@ -0,0 +1,61 @@
--TEST--
RAR directory stream basic test
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--FILE--
<?php
echo "Root entries unencoded:\n";
$u = "rar://" .
dirname(__FILE__) . '/dirs_and_extra_headers.rar*';
$d = dir($u);
while (false !== ($entry = $d->read())) {
echo $entry."\n";
}
$d->close();
echo "\nRoot entries encoded:\n";
$u = "rar://" .
dirname(__FILE__) . '/dirs_and_extra_headers.rar';
$d = dir($u);
while (false !== ($entry = $d->read())) {
echo $entry."\n";
}
$d->close();
echo "\nSub-root directory entries unencoded:\n";
$u = "rar://" .
dirname(__FILE__) . '/dirs_and_extra_headers.rar*#%EF%AC%B0';
$d = dir($u);
while (false !== ($entry = $d->read())) {
echo $entry."\n";
}
echo "\nDone.\n";
--EXPECTF--
Root entries unencoded:
allow_everyone_ni
file1.txt
file2_אּ.txt
with_streams.txt
Root entries encoded:
allow_everyone_ni
file1.txt
file2_%EF%AC%B0.txt
with_streams.txt
%EF%AC%B0
Sub-root directory entries unencoded:
%2Fempty%2E
empty
file3.txt
file4_אּ.txt
אּ_2
Done.

17
tests/061.phpt Normal file
View File

@@ -0,0 +1,17 @@
--TEST--
RAR directory stream attempt on file
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--FILE--
<?php
$u = "rar://" .
dirname(__FILE__) . '/dirlink_unix.rar' .
"#file";
var_dump(opendir($u));
echo "Done.\n";
--EXPECTF--
Warning: opendir(rar://%sdirlink_unix.rar#file): %cailed to open dir%S: Archive %sdirlink_unix.rar has an entry named file, but it is not a directory in %s on line %d
bool(false)
Done.

70
tests/062.phpt Normal file
View File

@@ -0,0 +1,70 @@
--TEST--
RAR directory stream stat
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--ENV--
TZ=Europe/Lisbon
--FILE--
<?php
umask(0);
echo "Root:\n";
$u = "rar://" .
dirname(__FILE__) . '/dirs_and_extra_headers.rar';
print_r(array_slice(fstat(opendir($u)), 13));
echo "\nSub-root directory:\n";
$u = "rar://" .
dirname(__FILE__) . '/dirs_and_extra_headers.rar#%EF%AC%B0';
$r = array_slice(fstat(opendir($u)), 13);
if (PHP_OS == 'WINNT') {
// we don't give the correct values on windows
$r['atime'] = 1272938643;
$r['mtime'] = 1272938643;
$r['ctime'] = 1272813170;
}
print_r($r);
echo "Done.\n";
--EXPECTF--
Root:
Array
(
[dev] => 0
[ino] => 0
[mode] => 16895
[nlink] => 1
[uid] => 0
[gid] => 0
[rdev] => 0
[size] => 0
[atime] => 0
[mtime] => 312768000
[ctime] => 0
[blksize] => %s
[blocks] => %s
)
Sub-root directory:
Array
(
[dev] => 0
[ino] => 0
[mode] => 16895
[nlink] => 1
[uid] => 0
[gid] => 0
[rdev] => 0
[size] => 0
[atime] => 1272938643
[mtime] => 1272938643
[ctime] => 1272813170
[blksize] => %s
[blocks] => %s
)
Done.

30
tests/063.phpt Normal file
View File

@@ -0,0 +1,30 @@
--TEST--
RAR directory stream stat consistency with url stat
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--FILE--
<?php
echo "Root:\n";
$u = "rar://" .
dirname(__FILE__) . '/dirs_and_extra_headers.rar';
var_dump(fstat(opendir($u)) == stat($u));
echo "\nSub-root directory:\n";
$u = "rar://" .
dirname(__FILE__) . '/dirs_and_extra_headers.rar#%EF%AC%B0';
var_dump(fstat(opendir($u)) == stat($u));
echo "Done.\n";
--EXPECTF--
Root:
bool(true)
Sub-root directory:
bool(true)
Done.

51
tests/064.phpt Normal file
View File

@@ -0,0 +1,51 @@
--TEST--
RAR directory-aware traversal with directory streams
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--FILE--
<?php
$a = "rar://" . dirname(__FILE__) . '/dirs_and_extra_headers.rar';
$stack = array();
$dh = opendir($a);
if ($dh) {
array_push($stack, array("", $dh));
}
$indent = 0;
while (!empty($stack)) {
$arr = array_pop($stack);
$prefix = $arr[0];
$cd = $arr[1];
while (($file = readdir($cd)) !== false) {
$u = $a . "#" . $prefix . "/" . $file;
$isdir = is_dir($u);
echo str_repeat(" ", $indent) .
"- ".rawurldecode($file)." ". ($isdir?"(dir)":""). "\n";
if ($isdir) {
if (($dh = opendir($u)) === false)
die("could not open $u");
$indent++;
array_push($stack, array($prefix, $cd));
$cd = $dh;
$prefix = $prefix . "/" . $file;
}
}
$indent--;
}
echo "Done.\n";
--EXPECTF--
- allow_everyone_ni (dir)
- file1.txt
- file2_אּ.txt
- with_streams.txt
- אּ (dir)
- %2Fempty%2E (dir)
- file7.txt
- empty (dir)
- file3.txt
- file4_אּ.txt
- אּ_2 (dir)
- file5.txt
- file6_אּ.txt
Done.

57
tests/065.phpt Normal file
View File

@@ -0,0 +1,57 @@
--TEST--
Directory streams compatibility with RecursiveDirectoryIterator
--SKIPIF--
<?php
if(!extension_loaded("rar")) die("skip");
--FILE--
<?php
$a = "rar://" . dirname(__FILE__) . '/dirs_and_extra_headers.rar#';
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($a),
RecursiveIteratorIterator::LEAVES_ONLY);
$it->rewind();
while($it->valid()) {
if (!$it->isDot()) {
echo 'SubPathName: ' . rawurldecode($it->getSubPathName()) . "\n";
echo 'SubPath: ' . rawurldecode($it->getSubPath()) . "\n";
echo 'Key: ' . $it->key() . "\n\n";
}
$it->next();
}
echo "Done.\n";
--EXPECTF--
SubPathName: file1.txt
SubPath:
Key: rar://%s/dirs_and_extra_headers.rar#%sfile1.txt
SubPathName: file2_אּ.txt
SubPath:
Key: rar://%s/dirs_and_extra_headers.rar#%sfile2_%EF%AC%B0.txt
SubPathName: with_streams.txt
SubPath:
Key: rar://%s/dirs_and_extra_headers.rar#%swith_streams.txt
SubPathName: אּ%s%2Fempty%2E%sfile7.txt
SubPath: אּ%s%2Fempty%2E
Key: rar://%s/dirs_and_extra_headers.rar#%s%EF%AC%B0%s%252Fempty%252E%sfile7.txt
SubPathName: אּ%sfile3.txt
SubPath: אּ
Key: rar://%s/dirs_and_extra_headers.rar#%s%EF%AC%B0%sfile3.txt
SubPathName: אּ%sfile4_אּ.txt
SubPath: אּ
Key: rar://%s/dirs_and_extra_headers.rar#%s%EF%AC%B0%sfile4_%EF%AC%B0.txt
SubPathName: אּ%sאּ_2%sfile5.txt
SubPath: אּ%sאּ_2
Key: rar://%s/dirs_and_extra_headers.rar#%s%EF%AC%B0%s%EF%AC%B0_2%sfile5.txt
SubPathName: אּ%sאּ_2%sfile6_אּ.txt
SubPath: אּ%sאּ_2
Key: rar://%s/dirs_and_extra_headers.rar#%s%EF%AC%B0%s%EF%AC%B0_2%sfile6_%EF%AC%B0.txt
Done.

Some files were not shown because too many files have changed in this diff Show More