Skip to content
This repository was archived by the owner on Jan 13, 2019. It is now read-only.
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: udan11/php-xz
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: codemasher/php-ext-xz
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
Able to merge. These branches can be automatically merged.

Commits on Apr 29, 2019

  1. 🔥

    codemasher committed Apr 29, 2019
    Copy the full SHA
    a22a82b View commit details
  2. 🔥

    codemasher committed Apr 29, 2019
    Copy the full SHA
    2f974f2 View commit details
  3. 🔥 R.I.P. PHP 5

    codemasher committed Apr 29, 2019
    Copy the full SHA
    cca5e5c View commit details
  4. :octocat: link updates

    codemasher committed Apr 29, 2019
    Copy the full SHA
    38420d6 View commit details
  5. :octocat:

    codemasher committed Apr 29, 2019
    Copy the full SHA
    b9f6e71 View commit details
  6. :octocat:

    codemasher committed Apr 29, 2019
    Copy the full SHA
    193d8d6 View commit details
  7. :octocat:

    codemasher committed Apr 29, 2019
    Copy the full SHA
    39e64ad View commit details
  8. codemasher committed Apr 29, 2019
    Copy the full SHA
    dd58951 View commit details

Commits on May 4, 2019

  1. :octocat:

    codemasher committed May 4, 2019
    Copy the full SHA
    f8a6170 View commit details

Commits on Oct 22, 2019

  1. :octocat: build status fix

    codemasher committed Oct 22, 2019
    Copy the full SHA
    dc8392b View commit details

Commits on Nov 6, 2020

  1. Copy the full SHA
    9405712 View commit details
  2. 🔥 type fixes

    codemasher committed Nov 6, 2020
    Copy the full SHA
    6125bae View commit details
  3. :octocat:

    codemasher committed Nov 6, 2020
    Copy the full SHA
    21cb3c3 View commit details
  4. :octocat: fix arginfo

    codemasher committed Nov 6, 2020
    Copy the full SHA
    012f9e5 View commit details
  5. :octocat: fix arginfo

    codemasher committed Nov 6, 2020
    Copy the full SHA
    0ac8f7b View commit details
  6. codemasher committed Nov 6, 2020
    Copy the full SHA
    375fefb View commit details
  7. :octocat:

    codemasher committed Nov 6, 2020
    Copy the full SHA
    bfc835e View commit details
  8. :octocat:

    codemasher committed Nov 6, 2020
    Copy the full SHA
    27801a2 View commit details
  9. :octocat:

    codemasher committed Nov 6, 2020
    Copy the full SHA
    6da08ab View commit details
  10. :octocat:

    codemasher committed Nov 6, 2020
    Copy the full SHA
    9942f3d View commit details
  11. :octocat:

    codemasher committed Nov 6, 2020
    Copy the full SHA
    b25fd19 View commit details
  12. :octocat:

    codemasher committed Nov 6, 2020
    Copy the full SHA
    23563dd View commit details
  13. :octocat:

    codemasher committed Nov 6, 2020
    Copy the full SHA
    59db334 View commit details

Commits on Nov 7, 2020

  1. :octocat:

    codemasher committed Nov 7, 2020
    Copy the full SHA
    12adcf4 View commit details

Commits on Nov 8, 2020

  1. :octocat: i wonder if...

    codemasher committed Nov 8, 2020
    Copy the full SHA
    bee726c View commit details
  2. :octocat: i wonder if...

    codemasher committed Nov 8, 2020
    Copy the full SHA
    dd95a74 View commit details
  3. :octocat: nah

    codemasher committed Nov 8, 2020
    Copy the full SHA
    3c3fd28 View commit details

Commits on Nov 9, 2020

  1. Copy the full SHA
    6c6d327 View commit details
  2. :octocat: strict comparisons

    codemasher committed Nov 9, 2020
    Copy the full SHA
    eb5fc3a View commit details
  3. :octocat: windows config

    codemasher committed Nov 9, 2020
    Copy the full SHA
    73716f2 View commit details
  4. :octocat:

    codemasher committed Nov 9, 2020
    Copy the full SHA
    19e7e7d View commit details
  5. :octocat:

    codemasher committed Nov 9, 2020
    Copy the full SHA
    ee02d1f View commit details
  6. :octocat:

    codemasher committed Nov 9, 2020
    Copy the full SHA
    549f98e View commit details
  7. Copy the full SHA
    9a3b8c3 View commit details

Commits on Nov 10, 2020

  1. :octocat:

    codemasher committed Nov 10, 2020
    Copy the full SHA
    06495ed View commit details
  2. :octocat:

    codemasher committed Nov 10, 2020
    Copy the full SHA
    b7a5914 View commit details
  3. 🚿

    codemasher committed Nov 10, 2020
    Copy the full SHA
    1508cd9 View commit details
  4. Copy the full SHA
    b632778 View commit details
  5. :octocat:

    codemasher committed Nov 10, 2020
    Copy the full SHA
    82e52ec View commit details
  6. Copy the full SHA
    9c20f78 View commit details
  7. :octocat:

    codemasher committed Nov 10, 2020
    Copy the full SHA
    6c62077 View commit details

Commits on Jun 6, 2021

  1. :octocat: link update

    codemasher committed Jun 6, 2021
    Copy the full SHA
    84e8742 View commit details

Commits on Jul 9, 2021

  1. fix lib test

    remicollet committed Jul 9, 2021
    Copy the full SHA
    be78be9 View commit details
  2. rely on pkg-config

    remicollet committed Jul 9, 2021
    Copy the full SHA
    3ef5b4a View commit details
  3. Copy the full SHA
    b53da53 View commit details
  4. only 1 header + rows

    remicollet committed Jul 9, 2021
    Copy the full SHA
    1aa1b27 View commit details
  5. Merge pull request #1 from remicollet/issue-lib64

    Library check
    codemasher authored Jul 9, 2021
    Copy the full SHA
    d86b07c View commit details
  6. Merge pull request #2 from remicollet/issue-ver

    use extension version instead of PHP version
    codemasher authored Jul 9, 2021
    Copy the full SHA
    66dcd68 View commit details

Commits on Jul 10, 2021

  1. Copy the full SHA
    29cd566 View commit details
  2. Merge pull request #3 from remicollet/issue-warn

    fix arginfo and build warnings
    codemasher authored Jul 10, 2021
    Copy the full SHA
    6ebbf3d View commit details
Showing with 535 additions and 220 deletions.
  1. +1 −0 .github/FUNDING.yml
  2. +43 −0 .github/workflows/linux.yml
  3. +69 −0 .github/workflows/windows-php8.yml
  4. +26 −22 .gitignore
  5. +0 −25 .travis.yml
  6. +1 −1 LICENSE.txt → LICENSE
  7. +60 −18 README.md
  8. +28 −30 config.m4
  9. +17 −0 config.w32
  10. +10 −17 php_xz.h
  11. +3 −3 tests/xzcode_advanced.phpt
  12. +2 −2 tests/xzcode_basic.phpt
  13. +32 −0 tests/xzdecode.phpt
  14. +1 −1 tests/xzopen_basic.phpt
  15. +2 −2 tests/xzopen_error.phpt
  16. +63 −0 tests/xzstream.phpt
  17. +1 −1 tests/xzwrite_basic.phpt
  18. +2 −2 utils.c
  19. +1 −1 utils.h
  20. +63 −44 xz.c
  21. +110 −51 xz_fopen_wrapper.c
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ko_fi: codemasher
43 changes: 43 additions & 0 deletions .github/workflows/linux.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# https://help.github.com/en/categories/automating-your-workflow-with-github-actions

on:
- pull_request
- push

name: "Linux"

jobs:

linux:
name: "Build and Tests (Linux)"

strategy:
fail-fast: false
matrix:
os: ["ubuntu-latest"]
php: ["8.3", "8.2", "8.1", "8.0", "7.4", "7.3", "7.2", "7.1", "7.0"]

runs-on: ${{ matrix.os }}

steps:
- name: "Install liblzma"
run: sudo apt-get install -y liblzma-dev

- name: "Checkout"
uses: actions/checkout@v3

- name: "Install PHP ${{ matrix.php }}"
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}

- name: "Compile extension"
run: |
phpize
./configure
make
sudo make install
- name: "Run tests"
run: make test

69 changes: 69 additions & 0 deletions .github/workflows/windows-php8.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# https://help.github.com/en/categories/automating-your-workflow-with-github-actions
# https://github.com/krakjoe/apcu/blob/5015af484a3f48289442cf1aff6a89f0f5aa3769/.github/workflows/config.yml

on:
- pull_request
- push

name: "Windows-PHP8"

jobs:

windows-php8:
name: "Build and Tests (Windows, PHP8)"

defaults:
run:
shell: cmd

strategy:
fail-fast: false
matrix:
php: ["8.3", "8.2", "8.1", "8.0"]
arch: ["x64"] #, "x86"
ts: ["ts", "nts"]

runs-on: windows-latest

steps:
- name: "Checkout"
uses: actions/checkout@v3

- name: "Install PHP SDK ${{matrix.php}}"
uses: codemasher/setup-php-sdk@no-toolkit
id: sdk
with:
version: ${{matrix.php}}
arch: ${{matrix.arch}}
ts: ${{matrix.ts}}
deps: liblzma

- name: "phpize"
run: phpize

- name: "configure build"
run: configure --enable-xz --with-prefix=${{steps.sdk.outputs.prefix}}

- name: "make"
run: nmake

- name: "test"
run: nmake test

- name: "Package"
run: |
md .artifact
copy ${{steps.sdk.outputs.buildpath}}\php_xz.dll .artifact\php_xz-${{steps.sdk.outputs.file_tag}}.dll
- name: "Upload artifacts"
uses: actions/upload-artifact@v3
if: contains(github.ref_type, 'branch')
with:
name: php_xz-php8-${{github.sha}}
path: .artifact

- name: "Attach file to release"
uses: softprops/action-gh-release@v1
if: contains(github.ref_type, 'tag')
with:
files: .artifact\php_xz-${{steps.sdk.outputs.file_tag}}.dll
48 changes: 26 additions & 22 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
# Object files
.deps
*.lo
*.la
.libs
*.o
Makefile*
acinclude.m4
aclocal.m4
autom4te.cache
ac*.m4
build
config*
config.guess
config.h
config.h.in
config.log
config.nice
config.status
config.sub
configure
configure.ac
configure.in
include
install-sh
libtool
ltmain.sh
Makefile
Makefile.fragments
Makefile.global
Makefile.objects
missing
mkinstalldirs
modules
run-tests.php
*.la
*.lo
# Libraries
*.lib
*.a

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib

# Executables
*.exe
*.out
*.app
tests/*/*.diff
tests/*/*.out
tests/*/*.php
tests/*/*.exp
tests/*/*.log
tests/*/*.sh
25 changes: 0 additions & 25 deletions .travis.yml

This file was deleted.

2 changes: 1 addition & 1 deletion LICENSE.txt → LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
--------------------------------------------------------------------
The PHP License, version 3.01
Copyright (c) 1999 - 2014 The PHP Group. All rights reserved.
Copyright (c) 1999 - 2019 The PHP Group. All rights reserved.
--------------------------------------------------------------------

Redistribution and use in source and binary forms, with or without
78 changes: 60 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,81 @@
php-xz
======
# php-ext-xz

[![Build Status](https://travis-ci.org/udan11/php-xz.svg?branch=master)](https://travis-ci.org/udan11/php-xz)
PHP Extension providing XZ (LZMA2) compression/decompression functions.<br/>
(see [Implement lzma (xz?) compression](https://news-web.php.net/php.internals/106654))

PHP Extension providing XZ (LZMA2) compression/decompression functions.
[![Linux build](https://github.com/codemasher/php-ext-xz/workflows/Linux/badge.svg)](https://github.com/codemasher/php-ext-xz/actions/workflows/linux.yml)
[![Windows PHP8 build](https://github.com/codemasher/php-ext-xz/workflows/Windows-PHP8/badge.svg)](https://github.com/codemasher/php-ext-xz/actions/workflows/windows-php8.yml)

## Installation
## Build & Installation

To install as module, perform the following steps:
### Linux

This module requires [`liblzma-dev`](https://packages.ubuntu.com/search?lang=de&keywords=liblzma-dev&searchon=names) (https://tukaani.org/xz/) as well as php7-dev or php8-dev.
If you are using Ubuntu, you can easily install all of them by typing the following command in your terminal:
```bash
git clone https://github.com/udan11/php-xz
cd php-xz && phpize && ./configure && make && sudo make install
sudo apt-get install git php7.4-dev liblzma-dev
```
To build and install as module, perform the following steps:
```bash
git clone https://github.com/codemasher/php-ext-xz.git
cd php-ext-xz
phpize
./configure
make
sudo make install
```

Do not forget to add `extension = xz.so` to your `php.ini`.
Do not forget to add `extension=xz.so` to your `php.ini`.

## Requirements
### Windows
Windows builds are now done automatically on each push; you can download them from the [build artifacts](https://docs.github.com/en/actions/managing-workflow-runs/downloading-workflow-artifacts) or [releases](https://github.com/codemasher/php-ext-xz/releases) (after 1.1.2).

This module depends on `git`, `php5-dev` and `liblzma-dev`. If you are using Ubuntu, you can easily install all of them by typing the following command in your terminal:
If you want to build it on your own, follow the steps under "[Build your own PHP on Windows](https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2)" to setup your build environment.
Before the compilation step, clone this repository to `[...]\php-src\ext\xz` and proceed.

```bash
sudo apt-get install git php5-dev liblzma-dev
```bat
git clone https://github.com/Microsoft/php-sdk-binary-tools.git c:\php-sdk
cd c:\php-sdk
phpsdk-vs16-x64.bat
```
Run the buildtree script and check out the php source:
```bat
phpsdk_buildtree php-8.0
git clone https://github.com/php/php-src.git
cd php-src
git checkout PHP-8.0
```
Clone the xz extension and run the build:
```bat
git clone https://github.com/codemasher/php-ext-xz .\ext\xz
phpsdk_deps -u
buildconf --force
configure --enable-xz
nmake snap
```

Please note that the `liblzma` dependency is not included with PHP < 8, so you will need to [download it manually](https://windows.php.net/downloads/php-sdk/deps/vs16/x64/liblzma-5.2.5-vs16-x64.zip) and extract it into the `deps` directory.

Copy the `php_xz.dll` into the `/ext` directory of your PHP installation and add the line `extension=xz` to your `php.ini` or in case of the versioned .dll from the artifacts something like: `extension=xz-0eebbf2-8.2-ts-vs16-x64` - omit the `php_` and `.dll`.

## Basic usage

```php
<?php

$fh = xzopen("/tmp/test.xz", "w");
xzwrite($fh, "Data you would like compressed and written.\n");
$fh = xzopen('/tmp/test.xz', 'w');
xzwrite($fh, 'Data you would like compressed and written.');
xzclose($fh);

$fh = xzopen("/tmp/test.xz", "r");
$fh = xzopen('/tmp/test.xz', 'r');
xzpassthru($fh);
xzclose($fh);
```

```php
$str = 'Data you would like compressed.';

$encoded = xzencode($str);
$decoded = xzdecode($encoded);
```

## Disclaimer
May or may not contain bugs. Use at your own risk.
58 changes: 28 additions & 30 deletions config.m4
Original file line number Diff line number Diff line change
@@ -1,39 +1,37 @@
dnl +----------------------------------------------------------------------+
dnl | PHP Version 5 |
dnl +----------------------------------------------------------------------+
dnl | Copyright (c) 1997-2015 The PHP Group |
dnl +----------------------------------------------------------------------+
dnl | This source file is subject to version 3.01 of the PHP license, |
dnl | that is bundled with this package in the file LICENSE, and is |
dnl | available through the world-wide-web at the following url: |
dnl | http://www.php.net/license/3_01.txt |
dnl | If you did not receive a copy of the PHP license and are unable to |
dnl | obtain it through the world-wide-web, please send a note to |
dnl | license@php.net so we can mail you a copy immediately. |
dnl +----------------------------------------------------------------------+
dnl | Authors: Payden Sutherland <payden@paydensutherland.com> |
dnl | Dan Ungureanu <udan1107@gmail.com> |
dnl | authors of the `zlib` extension (for guidance) |
dnl +----------------------------------------------------------------------+

PHP_ARG_WITH(xz, for xz support,
[ --with-xz Include xz support])
dnl config.m4 for extension xz

PHP_ARG_WITH([xz],
[for xz support],
[AS_HELP_STRING([--with-xz],
[Include xz support])])

if test "$PHP_XZ" != "no"; then

LIBNAME=lzma # you may want to change this
LIBSYMBOL=lzma_stream_encoder # you most likely want to change this

PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
[
PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $XZ_DIR/lib, XZ_SHARED_LIBADD)
AC_DEFINE(HAVE_XZLIB,1,[ ])
],[
AC_MSG_ERROR([wrong xz lib version or lib not found])
],[
-L$XZ_DIR/lib -lm
])
AC_PATH_PROG(PKG_CONFIG, pkg-config, no)

AC_MSG_CHECKING(for liblzma)
if test -x "$PKG_CONFIG" && $PKG_CONFIG --exists liblzma; then
LIBLZMA_INCLINE=`$PKG_CONFIG liblzma --cflags`
LIBLZMA_LIBLINE=`$PKG_CONFIG liblzma --libs`
LIBLZMA_VERSION=`$PKG_CONFIG liblzma --modversion`
AC_MSG_RESULT(from pkg-config: version $LIBLZMA_VERSION)
PHP_EVAL_LIBLINE($LIBLZMA_LIBLINE, XZ_SHARED_LIBADD)
PHP_EVAL_INCLINE($LIBLZMA_INCLINE)
else
AC_MSG_WARN([not found using pkg-config, fallback to system directory])

PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
[
PHP_ADD_LIBRARY($LIBNAME, 1, XZ_SHARED_LIBADD)
],[
AC_MSG_ERROR([wrong xz lib version or lib not found])
])
fi

PHP_SUBST(XZ_SHARED_LIBADD)

PHP_NEW_EXTENSION(xz, xz.c xz_fopen_wrapper.c utils.c, $ext_shared)
PHP_NEW_EXTENSION(xz, xz.c xz_fopen_wrapper.c utils.c, $ext_shared, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
fi
17 changes: 17 additions & 0 deletions config.w32
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// vim:ft=javascript

ARG_ENABLE('xz', 'xz support', 'no');

if (PHP_XZ != 'no') {
// liblzma is included with the ext-zip dependencies in php8
if(CHECK_LIB('liblzma_a.lib', 'xz', PHP_PHP_BUILD + '\\lib') &&
CHECK_HEADER_ADD_INCLUDE('lzma.h', 'CFLAGS_XZ', PHP_PHP_BUILD + '\\include')
){
AC_DEFINE('HAVE_XZ', 1, 'xz support enabled');

EXTENSION('xz', 'xz.c xz_fopen_wrapper.c utils.c', true, '/D LZMA_API_STATIC /DZEND_ENABLE_STATIC_TSRMLS_CACHE=1');
}
else{
WARNING('xz not enabled; libraries and headers not found');
}
}
27 changes: 10 additions & 17 deletions php_xz.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2015 The PHP Group |
| Copyright (c) 2019 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -15,19 +13,22 @@
| Authors: Payden Sutherland <payden@paydensutherland.com> |
| Dan Ungureanu <udan1107@gmail.com> |
| authors of the `zlib` extension (for guidance) |
| krakjoe (updated for PHP 7) |
+----------------------------------------------------------------------+
*/

#ifndef PHP_XZ_H
#define PHP_XZ_H
# define PHP_XZ_H

#define PHP_XZ_VERSION "1.1.2"

extern zend_module_entry xz_module_entry;
extern php_stream_wrapper php_stream_xz_wrapper;

#define phpext_xz_ptr &xz_module_entry
# define phpext_xz_ptr &xz_module_entry

/* The default size of the buffer used for compression and decompression. */
#define XZ_BUFFER_SIZE 4096
#define XZ_BUFFER_SIZE 4096

#ifdef PHP_WIN32
# define PHP_XZ_API __declspec(dllexport)
@@ -50,17 +51,9 @@ PHP_FUNCTION(xzopen);
PHP_FUNCTION(xzencode);
PHP_FUNCTION(xzdecode);

php_stream *php_stream_xzopen(php_stream_wrapper *wrapper, const char *path,
const char *mode_pass, int options, char **opened_path,
php_stream_context *context STREAMS_DC TSRMLS_DC);
php_stream *php_stream_xzopen(php_stream_wrapper *wrapper, const char *path, const char *mode_pass, int options, zend_string **opened_path, php_stream_context *context STREAMS_DC);

#ifdef ZTS
# define XZ_G(v) TSRMG(xz_globals_id, zend_xz_globals *, v)
#else
# define XZ_G(v) (xz_globals.v)
#endif

#endif
#endif /* PHP_XZ_H */

/*
* Local variables:
@@ -69,4 +62,4 @@ php_stream *php_stream_xzopen(php_stream_wrapper *wrapper, const char *path,
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/
*/
6 changes: 3 additions & 3 deletions tests/xzcode_advanced.phpt
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ Test `xzencode` and `xzdecode`: big inputs.
--SKIPIF--
<?php
if (!extension_loaded("xz")) {
print("XZ extension is not loaded!");
die("skip XZ extension is not loaded!");
}
?>
--FILE--
@@ -43,12 +43,12 @@ for ($i = 0; $i < $chunkNumber; ++$i) {
$str .= $chunk;
}

var_dump($chunkSize * $chunkNumber == strlen($str));
var_dump(($chunkSize * $chunkNumber) === strlen($str));
$encoded = xzencode($str);
print("encoding finished\n");
$decoded = xzdecode($encoded);
print("decoding finished\n");
var_dump($str == $decoded);
var_dump($str === $decoded);

?>
--EXPECTF--
4 changes: 2 additions & 2 deletions tests/xzcode_basic.phpt
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ Test `xzencode` and `xzdecode`: basic functionality.
--SKIPIF--
<?php
if (!extension_loaded("xz")) {
print("XZ extension is not loaded!");
die("skip XZ extension is not loaded!");
}
?>
--FILE--
@@ -20,7 +20,7 @@ In the Land of Mordor where the Shadows lie";
$encoded = xzencode($str);
$decoded = xzdecode($encoded);

var_dump($str == $decoded);
var_dump($str === $decoded);
?>
--EXPECTF--
bool(true)
32 changes: 32 additions & 0 deletions tests/xzdecode.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
--TEST--
Test `xzdecode` simple case
--SKIPIF--
<?php
if (!extension_loaded("xz")) {
die("skip XZ extension is not loaded!");
}
?>
--FILE--
<?php

$str = file_get_contents(__FILE__);

$encoded = xzencode($str);
print("encoding finished\n");
$decoded = xzdecode($encoded);
print("decoding finished\n");
var_dump($str === $decoded);

print("empty string\n");
var_dump(xzdecode(""));
print("garbage\n");
var_dump(xzdecode("this is not XZ data"));
?>
--EXPECT--
encoding finished
decoding finished
bool(true)
empty string
bool(false)
garbage
bool(false)
2 changes: 1 addition & 1 deletion tests/xzopen_basic.phpt
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ Test `xzopen`: basic functionality.
--SKIPIF--
<?php
if (!extension_loaded("xz")) {
print("XZ extension is not loaded!");
die("skip XZ extension is not loaded!");
}
?>
--FILE--
4 changes: 2 additions & 2 deletions tests/xzopen_error.phpt
Original file line number Diff line number Diff line change
@@ -3,12 +3,12 @@ Test `xzopen`: error conditions.
--SKIPIF--
<?php
if (!extension_loaded("xz")) {
print("XZ extension is not loaded!");
die("skip XZ extension is not loaded!");
}
?>
--FILE--
<?php
var_dump(xzopen('/dev/null', 'a'));
var_dump(xzopen('./test.txt', 'a'));
?>
--EXPECTF--
Warning: xzopen(): Can only open in read (r) or write (w) mode.%s
63 changes: 63 additions & 0 deletions tests/xzstream.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
--TEST--
Test lzma stream
--SKIPIF--
<?php
if (!extension_loaded("xz")) {
die("skip XZ extension is not loaded!");
}
if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
?>
--FILE--
<?php
$tmp1 = tempnam(sys_get_temp_dir(), "LZMA");
$tmp2 = tempnam(sys_get_temp_dir(), "LZMA");
$tmp3 = tempnam(sys_get_temp_dir(), "LZMA");

$len0 = filesize(PHP_BINARY);

echo "Compress level 2 ($tmp1)\n";
$opts = [
'xz' => [
'compression_level' => '2',
'max_memory' => 0,
]
];
$ctx = stream_context_create($opts);
copy(PHP_BINARY, "compress.lzma://$tmp1");
$len1 = filesize($tmp1);
var_dump($len1 > 0);
var_dump($len1 <= $len0);

echo "Compress level 9 ($tmp2)\n";
$opts = [
'xz' => [
'compression_level' => '9',
'max_memory' => 64*1024*1024,
]
];
$ctx = stream_context_create($opts);
copy(PHP_BINARY, "compress.lzma://$tmp2", $ctx);
$len2 = filesize($tmp2);
var_dump($len2 > 0);
var_dump($len2 <= $len1);

echo "Uncompress ($tmp3)\n";
copy("compress.lzma://$tmp1", $tmp3);
$len3 = filesize($tmp3);
var_dump($len3 > 0);
var_dump($len3 == $len0);

unlink($tmp1);
unlink($tmp2);
unlink($tmp3);
?>
--EXPECTF--
Compress level 2 (%s)
bool(true)
bool(true)
Compress level 9 (%s)
bool(true)
bool(true)
Uncompress (%s)
bool(true)
bool(true)
2 changes: 1 addition & 1 deletion tests/xzwrite_basic.phpt
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ Test function xzwrite() by calling it with its expected arguments
--SKIPIF--
<?php
if (!extension_loaded("xz")) {
print("XZ extension is not loaded!");
die("skip XZ extension is not loaded!");
}
?>
--FILE--
4 changes: 2 additions & 2 deletions utils.c
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ void *memmerge(void *ptr1, void *ptr2, size_t len1, size_t len2) /* {{{ */
if (ptr1 == NULL) {
return NULL;
}
memcpy(ptr1 + len1, ptr2, len2);
memcpy((char *)ptr1 + len1, ptr2, len2);
return ptr1;
}
/* }}} */
@@ -41,4 +41,4 @@ void *memmerge(void *ptr1, void *ptr2, size_t len1, size_t len2) /* {{{ */
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/
*/
2 changes: 1 addition & 1 deletion utils.h
Original file line number Diff line number Diff line change
@@ -35,4 +35,4 @@ void *memmerge(void *ptr1, void *ptr2, size_t len1, size_t len2);
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/
*/
107 changes: 63 additions & 44 deletions xz.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2015 The PHP Group |
| Copyright (c) 2019 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -15,32 +13,37 @@
| Authors: Payden Sutherland <payden@paydensutherland.com> |
| Dan Ungureanu <udan1107@gmail.com> |
| authors of the `zlib` extension (for guidance) |
| krakjoe (updated for PHP 7) |
+----------------------------------------------------------------------+
*/

#include <lzma.h>

#ifdef HAVE_CONFIG_H
# include "config.h"
# include "config.h"
#endif

#include "php.h"
#include "php_ini.h"

#include "ext/standard/file.h"
#include "ext/standard/info.h"

#include "utils.h"

#include "php_xz.h"

/* For compatibility with older PHP versions */
#ifndef ZEND_PARSE_PARAMETERS_NONE
#define ZEND_PARSE_PARAMETERS_NONE() \
ZEND_PARSE_PARAMETERS_START(0, 0) \
ZEND_PARSE_PARAMETERS_END()
#endif

/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO(arginfo_xzread, 0)
ZEND_ARG_INFO(0, fp)
ZEND_ARG_INFO(0, length)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO(arginfo_xzwrite, 0)
ZEND_BEGIN_ARG_INFO_EX(arginfo_xzwrite, 0, 0, 2)
ZEND_ARG_INFO(0, fp)
ZEND_ARG_INFO(0, str)
ZEND_ARG_INFO(0, length)
@@ -61,50 +64,42 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_xzdecode, 0)
ZEND_ARG_INFO(0, str)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_xzopen, 0, 0, 2)
ZEND_ARG_INFO(0, filename)
ZEND_ARG_INFO(0, mode)
ZEND_ARG_INFO(0, compression_level)
ZEND_END_ARG_INFO()
/* }}} */

/* {{{ xz_functions[]
Table containing functions exported by this module. */
const zend_function_entry xz_functions[] = {
PHP_FE(xzdecode, NULL)
PHP_FE(xzopen, NULL)
PHP_FE(xzencode, NULL)
/* {{{ xz_functions[] */
static const zend_function_entry xz_functions[] = {
PHP_FE(xzdecode, arginfo_xzdecode)
PHP_FE(xzopen, arginfo_xzopen)
PHP_FE(xzencode, arginfo_xzencode)
PHP_FALIAS(xzread, fread, arginfo_xzread)
PHP_FALIAS(xzwrite, fwrite, arginfo_xzwrite)
PHP_FALIAS(xzclose, fclose, arginfo_xzclose)
PHP_FALIAS(xzpassthru, fpassthru, arginfo_xzpassthru)
#ifndef PHP_FE_END
{ NULL, NULL, NULL, 0, 0 }
#else
PHP_FE_END
#endif
};
/* }}} */

/* {{{ xz_module_entry
Table describing module. */
/* {{{ xz_module_entry */
zend_module_entry xz_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"xz",
xz_functions,
PHP_MINIT(xz),
PHP_MSHUTDOWN(xz),
NULL, /* PHP_RINIT */
NULL, /* PHP_RSHUTDOWN */
NULL, /* PHP_RINIT(xz) */
NULL, /* PHP_RSHUTDOWN(xz) */
PHP_MINFO(xz),
#if ZEND_MODULE_API_NO >= 20010901
"0.1.1",
#endif
PHP_XZ_VERSION,
STANDARD_MODULE_PROPERTIES
};
/* }}} */

#ifdef COMPILE_DL_XZ
ZEND_GET_MODULE(xz)
#endif

/* {{{ INI entries. */
PHP_INI_BEGIN()

@@ -123,15 +118,15 @@ PHP_INI_END()
PHP_MINIT_FUNCTION(xz)
{
REGISTER_INI_ENTRIES();
php_register_url_stream_wrapper("compress.lzma", &php_stream_xz_wrapper TSRMLS_CC);
php_register_url_stream_wrapper("compress.lzma", &php_stream_xz_wrapper);
return SUCCESS;
}
/* }}} */

/* {{{ MSHUTDOWN */
PHP_MSHUTDOWN_FUNCTION(xz)
{
php_unregister_url_stream_wrapper("compress.lzma" TSRMLS_CC);
php_unregister_url_stream_wrapper("compress.lzma");
UNREGISTER_INI_ENTRIES();
return SUCCESS;
}
@@ -142,7 +137,13 @@ PHP_MINFO_FUNCTION(xz)
{
php_info_print_table_start();
php_info_print_table_header(2, "xz support", "enabled");
php_info_print_table_header(2, "liblzma version", lzma_version_string());
php_info_print_table_row(2, "xz extension version ", PHP_XZ_VERSION);
if (strcmp(LZMA_VERSION_STRING, lzma_version_string())) {
php_info_print_table_row(2, "liblzma headers version", LZMA_VERSION_STRING);
php_info_print_table_row(2, "liblzma library version", lzma_version_string());
} else {
php_info_print_table_row(2, "liblzma version", lzma_version_string());
}
php_info_print_table_end();

DISPLAY_INI_ENTRIES();
@@ -154,17 +155,17 @@ PHP_MINFO_FUNCTION(xz)
PHP_FUNCTION(xzopen)
{
char *filename = NULL, *mode = NULL;
size_t filename_len = 0, mode_len = 0;
unsigned long compression_level = INI_INT("xz.compression_level");
zend_long filename_len = 0, mode_len = 0;
zend_ulong compression_level = INI_INT("xz.compression_level");

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &filename, &filename_len, &mode, &mode_len, &compression_level) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|l", &filename, &filename_len, &mode, &mode_len, &compression_level) == FAILURE) {
return;
}

char *mode_to_pass = emalloc(mode_len + 32);
snprintf(mode_to_pass, mode_len + 32, "%s:%lu", mode, compression_level);

php_stream *stream = php_stream_xzopen(NULL, filename, mode_to_pass, 0, NULL, NULL STREAMS_CC TSRMLS_CC);
php_stream *stream = php_stream_xzopen(NULL, filename, mode_to_pass, 0, NULL, NULL STREAMS_CC);

if (!stream) {
RETURN_BOOL(0);
@@ -183,7 +184,7 @@ PHP_FUNCTION(xzencode)
/* The length of the string to be encoded */
size_t in_len = 0;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &in, &in_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &in, &in_len) == FAILURE) {
return;
}

@@ -255,7 +256,7 @@ PHP_FUNCTION(xzencode)

lzma_end(&strm);

RETURN_STRINGL(out, out_len, 0);
RETURN_STRINGL((char *)out, out_len);
}
/* }}} */

@@ -268,10 +269,14 @@ PHP_FUNCTION(xzdecode)
/* The length of the string to be encoded */
size_t in_len = 0;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &in, &in_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &in, &in_len) == FAILURE) {
return;
}

if (!in_len) {
RETURN_BOOL(0); /* empty string is not xz data */
}

/* The output string (encoded). */
uint8_t *out = NULL;
/* The length of the output string. */
@@ -299,6 +304,14 @@ PHP_FUNCTION(xzdecode)
lzma_ret status = LZMA_OK;
while (strm.avail_in != 0) {
status = lzma_code(&strm, LZMA_RUN);
if (status != LZMA_OK && status != LZMA_STREAM_END) {
if (out) {
efree(out);
}
lzma_end(&strm);
RETURN_BOOL(0); /* probably not xz data */
}

/* More memory is required. */
if (strm.avail_out == 0) {
out = memmerge(out, buff, out_len, XZ_BUFFER_SIZE);
@@ -307,22 +320,28 @@ PHP_FUNCTION(xzdecode)
strm.next_out = buff;
}
}

/* Merging last fragment. */
out = memmerge(out, buff, out_len, XZ_BUFFER_SIZE - strm.avail_out);
out_len += XZ_BUFFER_SIZE - strm.avail_out;

lzma_end(&strm);

RETURN_STRINGL(out, out_len, 0);
RETURN_STRINGL((char *)out, out_len);
}
/* }}} */

#ifdef COMPILE_DL_XZ
#ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE();
#endif
ZEND_GET_MODULE(xz)
#endif

/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/
*/
161 changes: 110 additions & 51 deletions xz_fopen_wrapper.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2015 The PHP Group |
| Copyright (c) 2019 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -15,14 +13,15 @@
| Authors: Payden Sutherland <payden@paydensutherland.com> |
| Dan Ungureanu <udan1107@gmail.com> |
| authors of the `zlib` extension (for guidance) |
| krakjoe (updated for PHP 7) |
+----------------------------------------------------------------------+
*/

#include <lzma.h>

#include "php.h"
#include "php_streams.h"
#include "fopen_wrappers.h"

#include "php_xz.h"

/* {{{ php_xz_stream_data_t */
@@ -54,51 +53,71 @@ struct php_xz_stream_data_t {
int fd;

/* The type of access required. */
char mode[4];
char mode[64];

/* Compression level used. */
unsigned long level;

/* The maximum amount of memory that can be used when decompressing. */
uint64_t memory;
};
/* }}} */

/* {{{ php_xz_decompress
Decompresses the stream. */
static int php_xz_decompress(struct php_xz_stream_data_t *self TSRMLS_DC)
Decompresses the stream.
Returns 0 on success, -1 on error
*/
static int php_xz_decompress(struct php_xz_stream_data_t *self)
{
lzma_stream *strm = &self->strm;
lzma_action action = LZMA_RUN;
lzma_ret ret;

if (strm->avail_in == 0 && !php_stream_eof(self->stream)) {
#if PHP_VERSION_ID >= 70400
ssize_t read = php_stream_read(self->stream, (char *)self->in_buf, self->in_buf_sz);
if (read < 0) {
return -1;
}
strm->avail_in = read;
#else
strm->avail_in = php_stream_read(self->stream, (char *)self->in_buf, self->in_buf_sz);
#endif
strm->next_in = self->in_buf;
strm->avail_in = php_stream_read(self->stream, self->in_buf, self->in_buf_sz);
}

lzma_ret ret = lzma_code(strm, action);

if (strm->avail_out == 0 && self->out_buf_idx == strm->next_out) {
/* All bytes in the output buffer have been read. */
strm->next_out = self->out_buf_idx = self->out_buf;
strm->avail_out = self->out_buf_sz;
ret = lzma_code(strm, action);
if (ret != LZMA_OK && ret != LZMA_STREAM_END) {
return -1;
}

return ret;
return 0;
}
/* }}} */

/* {{{ php_xz_compress
Compresses the stream by consuming all bytes in `lzma_stream->next_in` and
writing them into the file.
Returns the number of bytes to be written. */
static int php_xz_compress(struct php_xz_stream_data_t *self TSRMLS_DC)
Returns the number of bytes to be written or -1 on error
*/
static int php_xz_compress(struct php_xz_stream_data_t *self)
{
lzma_stream *strm = &self->strm;
lzma_action action = LZMA_RUN;
int wrote = 0, to_write = strm->avail_in;
int to_write = strm->avail_in;

while (strm->avail_in > 0) {
lzma_ret ret = lzma_code(strm, action);
size_t len = self->out_buf_sz - strm->avail_out;
php_stream_write(self->stream, self->out_buf, len);
if (ret != LZMA_OK) {
to_write = -1; /* error in compression */
break;
} else if (len) {
if (php_stream_write(self->stream, (char *)self->out_buf, len) != len) {
to_write = -1; /* error in output stream */
break;
}
}
strm->next_out = self->out_buf;
strm->avail_out = self->out_buf_sz;
}
@@ -115,8 +134,7 @@ static int php_xz_init_decoder(struct php_xz_stream_data_t *self)
{
lzma_stream *strm = &self->strm;

uint64_t mem = INI_INT("xz.max_memory");
if (lzma_auto_decoder(strm, mem ? mem : UINT64_MAX, LZMA_CONCATENATED) != LZMA_OK) {
if (lzma_auto_decoder(strm, self->memory ? self->memory : UINT64_MAX, LZMA_CONCATENATED) != LZMA_OK) {
return 0;
}

@@ -173,11 +191,16 @@ static int php_xz_init_encoder(struct php_xz_stream_data_t *self)

/* {{{ php_xziop_read
Reads from the stream. */
static size_t php_xziop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
#if PHP_VERSION_ID >= 70400
static ssize_t php_xziop_read(php_stream *stream, char *buf, size_t count)
#else
static size_t php_xziop_read(php_stream *stream, char *buf, size_t count)
#endif
{
struct php_xz_stream_data_t *self = (struct php_xz_stream_data_t *) stream->abstract;
lzma_stream *strm = &self->strm;


size_t to_read = count, have_read = 0;

while (to_read > 0) {
@@ -190,8 +213,12 @@ static size_t php_xziop_read(php_stream *stream, char *buf, size_t count TSRMLS_
memcpy(buf + have_read, self->out_buf_idx, strm->next_out - self->out_buf_idx);
have_read += strm->next_out - self->out_buf_idx;
to_read -= strm->next_out - self->out_buf_idx;
self->out_buf_idx = strm->next_out;
if (strm->next_out == self->out_buf_idx) {

if (strm->avail_out) {
self->out_buf_idx = strm->next_out;
} else {
/* All bytes in the output buffer have been read. */
self->out_buf_idx = strm->next_out;
self->out_buf_idx = strm->next_out = self->out_buf;
strm->avail_out = self->out_buf_sz;
}
@@ -202,7 +229,15 @@ static size_t php_xziop_read(php_stream *stream, char *buf, size_t count TSRMLS_
return have_read;
}

php_xz_decompress(self TSRMLS_CC);

if (php_xz_decompress(self) < 0) {
#if PHP_VERSION_ID >= 70400
if (!have_read) {
return -1;
}
#endif
break;
}
}

return have_read;
@@ -211,36 +246,44 @@ static size_t php_xziop_read(php_stream *stream, char *buf, size_t count TSRMLS_

/* {{{ php_xziop_write
Writes to the stream. */
static size_t php_xziop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
#if PHP_VERSION_ID >= 70400
static ssize_t php_xziop_write(php_stream *stream, const char *buf, size_t count)
#else
static size_t php_xziop_write(php_stream *stream, const char *buf, size_t count)
#endif
{
struct php_xz_stream_data_t *self = (struct php_xz_stream_data_t *) stream->abstract;
int wrote = 0, bytes_consumed = 0;
size_t wrote = 0, bytes_consumed = 0;

lzma_stream *strm = &self->strm;

while (count - wrote > self->in_buf_sz - strm->avail_in) {
/* Copy as many bytes into next_in buffer as we can. */
memcpy((void *)self->in_buf + strm->avail_in, buf + wrote, self->in_buf_sz - strm->avail_in);
memcpy((char *)self->in_buf + strm->avail_in, buf + wrote, self->in_buf_sz - strm->avail_in);
wrote += self->in_buf_sz - strm->avail_in;
strm->avail_in = self->in_buf_sz;
bytes_consumed = php_xz_compress(self TSRMLS_CC);
bytes_consumed = php_xz_compress(self);
if (bytes_consumed < 0) {
break;
}
}

if (count - wrote > 0) {
memcpy((void *) self->in_buf + strm->avail_in, buf + wrote, count - wrote);
memcpy((char *) self->in_buf + strm->avail_in, buf + wrote, count - wrote);
strm->avail_in += count - wrote;
}

return count;
#if PHP_VERSION_ID >= 70400
return (bytes_consumed < 0 ? -1 : count);
#else
return (bytes_consumed < 0 ? 0 : count);
#endif
}
/* }}} */

/* {{{ php_xziop_close
Closes the stream. */
static int php_xziop_close(php_stream *stream, int close_handle TSRMLS_DC)
static int php_xziop_close(php_stream *stream, int close_handle)
{
struct php_xz_stream_data_t *self = (struct php_xz_stream_data_t *) stream->abstract;
int ret = EOF;
@@ -259,7 +302,7 @@ static int php_xziop_close(php_stream *stream, int close_handle TSRMLS_DC)

if (strm->avail_out < self->out_buf_sz) {
size_t write_size = self->out_buf_sz - strm->avail_out;
php_stream_write(self->stream, self->out_buf, write_size);
php_stream_write(self->stream, (char *)self->out_buf, write_size);
strm->next_out = self->out_buf;
strm->avail_out = self->out_buf_sz;
}
@@ -283,11 +326,11 @@ static int php_xziop_close(php_stream *stream, int close_handle TSRMLS_DC)

/* {{{ php_xziop_flush
Flushes the stream. */
static int php_xziop_flush(php_stream *stream TSRMLS_DC)
static int php_xziop_flush(php_stream *stream)
{
struct php_xz_stream_data_t *self = (struct php_xz_stream_data_t *) stream->abstract;
if (strcmp(self->mode, "w") == 0 || strcmp(self->mode, "wb") == 0) {
php_xz_compress(self TSRMLS_CC);
php_xz_compress(self);
}
php_stream_flush(self->stream);
return 0;
@@ -305,27 +348,32 @@ php_stream_ops php_stream_xzio_ops = {
NULL, /* seek */
NULL, /* cast */
NULL, /* stat */
NULL /* set_option */
NULL, /* set_option */
.label = "XZ",
.write = php_xziop_write,
.read = php_xziop_read,
.close = php_xziop_close,
.flush = php_xziop_flush,
.seek = NULL,
.cast = NULL,
.stat = NULL,
.set_option = NULL
};
/* }}} */

/* {{{ php_stream_xzopen
Opens a stream. */
php_stream *php_stream_xzopen(php_stream_wrapper *wrapper, const char *path,
const char *mode_pass, int options, char **opened_path,
php_stream_context *context STREAMS_DC TSRMLS_DC)
php_stream *php_stream_xzopen(php_stream_wrapper *wrapper, const char *path, const char *mode_pass, int options, zend_string **opened_path, php_stream_context *context STREAMS_DC)
{
char mode[64];
unsigned long level = 6;
zend_ulong level = INI_INT("xz.compression_level");;
zend_ulong mem = INI_INT("xz.max_memory");

php_stream *stream = NULL, *innerstream = NULL;

strncpy(mode, mode_pass, sizeof(mode));
mode[sizeof(mode) - 1] = '\0';

/* The pointer below is freed even though it is `const` because it was
manually allocated in `xzopen`.. */
efree((void *) mode_pass);

/* Split compression level and mode. */
char *colonp = strchr(mode, ':');
if (colonp) {
@@ -334,19 +382,29 @@ php_stream *php_stream_xzopen(php_stream_wrapper *wrapper, const char *path,
}

if ((strchr(mode, '+')) || ((strchr(mode, 'r')) && (strchr(mode, 'w')))) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "cannot open xz stream for reading and writing at the same time.");
php_error_docref(NULL, E_ERROR, "cannot open xz stream for reading and writing at the same time.");
return NULL;
}

if ((level < 0) || (level > 9)) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid compression level");
php_error_docref(NULL, E_ERROR, "Invalid compression level");
return NULL;
}

if (strncasecmp("compress.lzma://", path, 16) == 0) {
path += 16;
}

if (context) {
zval *tmpzval;
if (NULL != (tmpzval = php_stream_context_get_option(context, "xz", "compression_level"))) {
level = zval_get_long(tmpzval);
}
if (NULL != (tmpzval = php_stream_context_get_option(context, "xz", "max_memory"))) {
mem = zval_get_long(tmpzval);
}
}

innerstream = php_stream_open_wrapper_ex(path, mode, STREAM_MUST_SEEK | options | STREAM_WILL_CAST, opened_path, context);

if (innerstream) {
@@ -356,35 +414,36 @@ php_stream *php_stream_xzopen(php_stream_wrapper *wrapper, const char *path,
self->stream = innerstream;
self->fd = fd;
self->level = level;
self->memory = mem;
strncpy(self->mode, mode, sizeof(self->mode));
stream = php_stream_alloc_rel(&php_stream_xzio_ops, self, 0, mode);

if (stream) {
stream->flags |= PHP_STREAM_FLAG_NO_BUFFER;
if ((strcmp(mode, "w") == 0) || (strcmp(mode, "wb") == 0)) {
if (!php_xz_init_encoder(self)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initialize xz encoder.");
php_error_docref(NULL, E_WARNING, "Could not initialize xz encoder.");
efree(self);
php_stream_close(stream);
return NULL;
}
} else if ((strcmp(mode, "r") == 0) || (strcmp(mode, "rb") == 0)) {
if (!php_xz_init_decoder(self)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initialize xz decoder");
php_error_docref(NULL, E_WARNING, "Could not initialize xz decoder");
efree(self);
php_stream_close(stream);
return NULL;
}
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can only open in read (r) or write (w) mode.");
php_error_docref(NULL, E_WARNING, "Can only open in read (r) or write (w) mode.");
efree(self);
php_stream_close(stream);
return NULL;
}
return stream;
}
efree(self);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed opening xz stream");
php_error_docref(NULL, E_WARNING, "failed opening xz stream");
}
php_stream_close(innerstream);
}
@@ -425,4 +484,4 @@ php_stream_wrapper php_stream_xz_wrapper = {
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/
*/