1 <?php
2
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
19 class rex_stream
20 {
21 private static $useRealFiles;
22
23 private static $registered = false;
24 private static $nextContent = [];
25
26 private $position;
27 private $content;
28
29 30 31 32 33 34 35 36 37 38
39 public static function factory($path, $content)
40 {
41 if (!is_string($path) || empty($path)) {
42 throw new InvalidArgumentException('Expecting $path to be a string and not empty!');
43 }
44 if (!is_string($content)) {
45 throw new InvalidArgumentException('Expecting $content to be a string!');
46 }
47
48 if (null === self::$useRealFiles) {
49 self::$useRealFiles = extension_loaded('suhosin')
50 && !preg_match('/(?:^|,)rex(?::|,|$)/', ini_get('suhosin.executor.include.whitelist'));
51 }
52
53 if (self::$useRealFiles) {
54 $hash = substr(sha1($content), 0, 7);
55 $path = rex_path::coreCache('stream/'.$path.'/'.$hash);
56
57 if (!file_exists($path)) {
58 rex_file::put($path, $content);
59 }
60
61 return $path;
62 }
63
64 if (!self::$registered) {
65 stream_wrapper_register('rex', self::class);
66 self::$registered = true;
67 }
68
69
70
71 $path = 'rex:///' . $path;
72 self::$nextContent[$path] = $content;
73
74 return $path;
75 }
76
77 78 79
80 public function stream_open($path, $mode, $options, &$opened_path)
81 {
82 if (!isset(self::$nextContent[$path]) || !is_string(self::$nextContent[$path])) {
83 return false;
84 }
85
86 $this->position = 0;
87 $this->content = self::$nextContent[$path];
88
89
90 return true;
91 }
92
93 94 95
96 public function stream_read($count)
97 {
98 $ret = substr($this->content, $this->position, $count);
99 $this->position += strlen($ret);
100 return $ret;
101 }
102
103 104 105
106 public function stream_eof()
107 {
108 return $this->position >= strlen($this->content);
109 }
110
111 112 113
114 public function stream_seek($offset, $whence = SEEK_SET)
115 {
116 switch ($whence) {
117 case SEEK_SET:
118 $this->position = $offset;
119 return true;
120 case SEEK_CUR:
121 $this->position += $offset;
122 return true;
123 case SEEK_END:
124 $this->position = strlen($this->content) - 1 + $offset;
125 return true;
126 default:
127 return false;
128 }
129 }
130
131 132 133
134 public function stream_tell()
135 {
136 return $this->position;
137 }
138
139 140 141
142 public function stream_flush()
143 {
144 return true;
145 }
146
147 148 149
150 public function stream_stat()
151 {
152 return null;
153 }
154
155 156 157
158 public function url_stat()
159 {
160 return null;
161 }
162 }
163