Issues (1513)

lib/utils/stringstreamwrapper.php (6 issues)

1
<?php
2
/*
3
 * SPDX-License-Identifier: AGPL-3.0-only
4
 * SPDX-FileCopyrightText: Copyright 2007-2013,2015-2016 Zarafa Deutschland GmbH
5
 * SPDX-FileCopyrightText: Copyright 2020-2022 grommunio GmbH
6
 *
7
 * Wraps a string as a standard php stream
8
 * The used method names are predefined and can not be altered.
9
 */
10
11
class StringStreamWrapper {
12
	public const PROTOCOL = "stringstream";
13
14
	private $stringstream;
15
	private $position;
16
	private $stringlength;
17
	private $truncateHtmlSafe;
18
	private $context;
19
20
	/**
21
	 * Opens the stream
22
	 * The string to be streamed is passed over the context.
23
	 *
24
	 * @param string $path        Specifies the URL that was passed to the original function
25
	 * @param string $mode        The mode used to open the file, as detailed for fopen()
26
	 * @param int    $options     Holds additional flags set by the streams API
27
	 * @param string $opened_path if the path is opened successfully, and STREAM_USE_PATH is set in options,
28
	 *                            opened_path should be set to the full path of the file/resource that was actually opened
29
	 *
30
	 * @return bool
31
	 */
32
	public function stream_open($path, $mode, $options, &$opened_path) {
0 ignored issues
show
The parameter $path is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

32
	public function stream_open(/** @scrutinizer ignore-unused */ $path, $mode, $options, &$opened_path) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $mode is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

32
	public function stream_open($path, /** @scrutinizer ignore-unused */ $mode, $options, &$opened_path) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $opened_path is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

32
	public function stream_open($path, $mode, $options, /** @scrutinizer ignore-unused */ &$opened_path) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $options is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

32
	public function stream_open($path, $mode, /** @scrutinizer ignore-unused */ $options, &$opened_path) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
33
		$contextOptions = stream_context_get_options($this->context);
34
		if (!isset($contextOptions[self::PROTOCOL]['string'])) {
35
			return false;
36
		}
37
38
		$this->position = 0;
39
40
		// this is our stream!
41
		$this->stringstream = $contextOptions[self::PROTOCOL]['string'];
42
		$this->truncateHtmlSafe = (isset($contextOptions[self::PROTOCOL]['truncatehtmlsafe'])) ? $contextOptions[self::PROTOCOL]['truncatehtmlsafe'] : false;
43
44
		$this->stringlength = strlen($this->stringstream);
45
		SLog::Write(LOGLEVEL_DEBUG, sprintf("StringStreamWrapper::stream_open(): initialized stream length: %d - HTML-safe-truncate: %s", $this->stringlength, Utils::PrintAsString($this->truncateHtmlSafe)));
0 ignored issues
show
It seems like $this->truncateHtmlSafe can also be of type false; however, parameter $var of Utils::PrintAsString() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

45
		SLog::Write(LOGLEVEL_DEBUG, sprintf("StringStreamWrapper::stream_open(): initialized stream length: %d - HTML-safe-truncate: %s", $this->stringlength, Utils::PrintAsString(/** @scrutinizer ignore-type */ $this->truncateHtmlSafe)));
Loading history...
46
47
		return true;
48
	}
49
50
	/**
51
	 * Reads from stream.
52
	 *
53
	 * @param int $len amount of bytes to be read
54
	 *
55
	 * @return string
56
	 */
57
	public function stream_read($len) {
58
		$data = substr($this->stringstream, $this->position, $len);
59
		$this->position += strlen($data);
60
61
		return $data;
62
	}
63
64
	/**
65
	 * Writes data to the stream.
66
	 *
67
	 * @param string $data
68
	 *
69
	 * @return int
70
	 */
71
	public function stream_write($data) {
72
		$l = strlen($data);
73
		$this->stringstream = substr($this->stringstream, 0, $this->position) . $data . substr($this->stringstream, $this->position += $l);
74
		$this->stringlength = strlen($this->stringstream);
75
76
		return $l;
77
	}
78
79
	/**
80
	 * Stream "seek" functionality.
81
	 *
82
	 * @param int $offset
83
	 * @param int $whence
84
	 *
85
	 * @return bool
86
	 */
87
	public function stream_seek($offset, $whence = SEEK_SET) {
88
		if ($whence == SEEK_CUR) {
89
			$this->position += $offset;
90
		}
91
		elseif ($whence == SEEK_END) {
92
			$this->position = $this->stringlength + $offset;
93
		}
94
		else {
95
			$this->position = $offset;
96
		}
97
98
		return true;
99
	}
100
101
	/**
102
	 * Returns the current position on stream.
103
	 *
104
	 * @return int
105
	 */
106
	public function stream_tell() {
107
		return $this->position;
108
	}
109
110
	/**
111
	 * Indicates if 'end of file' is reached.
112
	 *
113
	 * @return bool
114
	 */
115
	public function stream_eof() {
116
		return $this->position >= $this->stringlength;
117
	}
118
119
	/**
120
	 * Truncates the stream to the new size.
121
	 *
122
	 * @param int $new_size
123
	 *
124
	 * @return bool
125
	 */
126
	public function stream_truncate($new_size) {
127
		// cut the string!
128
		$this->stringstream = Utils::Utf8_truncate($this->stringstream, $new_size, $this->truncateHtmlSafe);
129
		$this->stringlength = strlen($this->stringstream);
130
131
		if ($this->position > $this->stringlength) {
132
			SLog::Write(LOGLEVEL_WARN, sprintf("StringStreamWrapper->stream_truncate(): stream position (%d) ahead of new size of %d. Repositioning pointer to end of stream.", $this->position, $this->stringlength));
133
			$this->position = $this->stringlength;
134
		}
135
136
		return true;
137
	}
138
139
	/**
140
	 * Retrieves information about a stream.
141
	 *
142
	 * @return array
143
	 */
144
	public function stream_stat() {
145
		return [
146
			7 => $this->stringlength,
147
			'size' => $this->stringlength,
148
		];
149
	}
150
151
	/**
152
	 * Instantiates a StringStreamWrapper.
153
	 *
154
	 * @param string $string           The string to be wrapped
155
	 * @param bool   $truncatehtmlsafe Indicates if a truncation should be done html-safe - default: false
156
	 *
157
	 * @return StringStreamWrapper
158
	 */
159
	public static function Open($string, $truncatehtmlsafe = false) {
160
		$context = stream_context_create([self::PROTOCOL => ['string' => &$string, 'truncatehtmlsafe' => $truncatehtmlsafe]]);
161
162
		return fopen(self::PROTOCOL . "://", 'r', false, $context);
0 ignored issues
show
Bug Best Practice introduced by
The expression return fopen(self::PROTO..., 'r', false, $context) returns the type resource which is incompatible with the documented return type StringStreamWrapper.
Loading history...
163
	}
164
}
165
166
stream_wrapper_register(StringStreamWrapper::PROTOCOL, "StringStreamWrapper");
167