├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── LICENCE
├── README.md
├── composer.json
├── composer.lock
├── doc
├── QAP1_protocol.txt
├── QAP_message.txt
└── original_version_simple.php
├── example
├── config.php
├── error_handling.php
├── evaluator.php
└── example1.php
├── phpunit.xml
├── rserve.R
├── src
├── ArrayWrapper.php
├── Connection.php
├── Evaluator.php
├── Exception.php
├── Parser.php
├── Parser
│ ├── Debug.php
│ ├── Exception.php
│ ├── NativeArray.php
│ └── REXP.php
├── Protocol.php
├── REXP.php
├── REXP
│ ├── Complex.php
│ ├── Dataframe.php
│ ├── Double.php
│ ├── Error.php
│ ├── Expression.php
│ ├── Factor.php
│ ├── GenericVector.php
│ ├── Integer.php
│ ├── Language.php
│ ├── Logical.php
│ ├── RList.php
│ ├── RNull.php
│ ├── RString.php
│ ├── Raw.php
│ ├── Symbol.php
│ ├── Unknown.php
│ └── Vector.php
├── Serializer.php
├── Session.php
├── autoload.php
└── lib
│ └── helpers.php
└── tests
├── .gitignore
├── BaseTest.php
├── ConnectionManager.php
├── Definition.php
├── LoginTest.php
├── ParserNativeTest.php
├── REXPTest.php
├── SessionTest.php
├── bootstrap.php
└── config.php.sample
/.gitignore:
--------------------------------------------------------------------------------
1 | .project
2 | .buildpath
3 | .settings
4 | vendor
5 | tests/BaseTest.php
6 | *.cache
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: required
2 |
3 | services:
4 | - docker
5 |
6 | language: php
7 |
8 | php:
9 | - 7
10 |
11 | before_install:
12 | - composer install
13 | - cp tests/config.php.sample tests/config.php
14 | - docker run -d -p 6311:6311 wnagele/rserve
15 |
16 | script:
17 | - composer test
18 |
19 | after_success:
20 | - docker ps|grep rserve|awk '{print "docker stop " $1}'|bash
21 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | # 2.1
3 |
4 | - Minimum php version 7.4
5 | - Fix php 8.0 compatibilites for NativeArray
6 | - Adapt code style for php 7.4, adding types
7 |
8 | # 2.0
9 |
10 | - All classes are declared under Sentiweb\Rserve namespace allowing PSR-4 autoloading
11 | - Parsers are now individualized into classes
12 | - A Parser instance can be directly used as second argument of evalString() to replace default parser (see example)
13 |
14 | # Before TDB
--------------------------------------------------------------------------------
/LICENCE:
--------------------------------------------------------------------------------
1 | rserve-php - php interface to R
2 | Copyright (C) 2010 Clément Turbelin, Simon Urbanek
3 |
4 | This library is free software; you can redistribute it and/or
5 | modify it under the terms of the GNU Lesser General Public
6 | License as published by the Free Software Foundation; either
7 | version 2.1 of the License, or (at your option) any later version.
8 |
9 | This library is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 | Lesser General Public License for more details.
13 |
14 | You should have received a copy of the GNU Lesser General Public
15 | License along with this library; if not, write to the Free Software
16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Rserve-php
2 | ==========
3 |
4 | php5 client for Rserve http://www.rforge.net/Rserve/ (a TCP/IP server for R statistical software)
5 |
6 | [](https://travis-ci.org/shadiakiki1986/rserve-php)
7 |
8 | Changes from 1.0 version
9 | ---
10 | - All classes are declared under Sentiweb\Rserve namespace allowing PSR-4 autoloading
11 | - Parsers are now individualized into classes
12 | - A Parser instance can be directly used as second argument of evalString() to replace default parser (see example)
13 |
14 | Tests
15 | -----
16 |
17 | You can run tests using phpunit
18 |
19 | Several tests need to have a running Rserve server (not handled by this library).
20 | To configure the test to use a server you have to configure the connection using environment vars or by creating a file in tests/config.php and defining constants (a sample file is available in tests/config.php.sample).
21 | Expected vars (in env or as constant in tests/config.php)
22 | - `RSERVE_HOST` : hostname or IP of the Rserve server (e.g. 'localhost' or 127.0.0.1 for local server).
23 | - `RSERVE_PORT` : port number, if value is '0' or 'unix', the HOST is expected to be a unix socket path.
24 | - `RSERVE_USER` : username if the Rserve server is expecting authentication, skip or leave empty if not
25 | - `RSERVE_PASS` : password if the Rserve server is expecting authentication, skip or leave empty if not
26 |
27 | `RSERVE_HOST` is required to be defined (either env or in config.php) to run the connection aware tests, if not these tests will be skipped.
28 |
29 | Credential-free tests
30 | * launch your credential-free Rserve instance
31 | * Can be done with `docker run -d -p 6311:6311 wnagele/rserve`
32 |
33 | * if installed with composer: `composer test`
34 | * otherwise, run with `phpunit`
35 |
36 | Login tests:
37 | This test suite require a credential-protected Rserve instance to be running (not provided by this library)
38 | and the credentials (username and password to be configured as described above)
39 |
40 | Installation
41 | ---------
42 |
43 | Using without composer :
44 | include src/autoload.php in your project
45 |
46 | Using with composer:
47 | * run `composer require cturbelin/rserve-php:2.0.x-dev`
48 | * add `require __DIR__.'/../vendor/autoload.php';` to your project
49 |
50 | Some usage example are provided in [example](example) directory
51 |
52 | Using Login Authorization
53 | -------------------------
54 | Usage is the same as the vanilla usage, except for the constructor
55 | ```php
56 | $cnx = new \Sentiweb\Rserve\Connection('myserverhost', 6311, ['username'=>username,'password'=>password])
57 | ```
58 |
59 | Parsers
60 | -----
61 |
62 | Results provided by R could be handled using several parsers
63 |
64 | - NativeArray
65 | Translates R structure into php simple arrays. It is useful to get simple values from R
66 |
67 | - Wrapped array
68 | Using NativeArray with parameters `array("wrapper"=>true)` in contructor return object
69 | with attributes of R objects.
70 | The result object can be used as an array and provides methods to access R object attributes
71 |
72 | - Debug
73 | Translates R response to structure useful for debugging
74 |
75 | - REXP
76 | Translates R response into REXP classes
77 |
78 |
79 | Async Mode
80 | -----------
81 |
82 | Several functions allow to use connection in async mode
83 |
84 | * getSocket() to get the socket an set some options
85 | * setAsync() allow to set the async mode
86 | * getResults($parser) : get and parse the results after a call to evalString() in async mode
87 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cturbelin/rserve-php",
3 | "type": "library",
4 | "description": "Rserve client library for PHP",
5 | "keywords": ["R","Rserve","Stats"],
6 | "homepage": "https://github.com/cturbelin/rserve-php",
7 | "licence": "LGPL-2.1",
8 | "authors": [
9 | {
10 | "name": "Clément Turbelin",
11 | "email": "clement.turbelin@gmail.com"
12 | }
13 | ],
14 | "require": {
15 | "php": ">=7.4"
16 | },
17 | "require-dev": {
18 | "phpunit/phpunit": "^9",
19 | "symplify/easy-coding-standard": "^12.0"
20 | },
21 | "autoload": {
22 | "files": ["src/lib/helpers.php"],
23 | "psr-4": {
24 | "Sentiweb\\Rserve\\": "src/",
25 | "Sentiweb\\Rserve\\Tests\\":"tests/"
26 | }
27 | },
28 | "autoload-dev": {
29 | "psr-4" : {
30 | "Sentiweb\\Rserve\\Tests\\":"tests/"
31 | }
32 | },
33 | "scripts": {
34 | "test": [
35 | "parallel-lint . --exclude vendor --exclude doc",
36 | "phpunit --verbose"
37 | ]
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5 | "This file is @generated automatically"
6 | ],
7 | "content-hash": "01af730bf1665ae13aa8da3f38260719",
8 | "packages": [],
9 | "packages-dev": [
10 | {
11 | "name": "doctrine/instantiator",
12 | "version": "1.5.0",
13 | "source": {
14 | "type": "git",
15 | "url": "https://github.com/doctrine/instantiator.git",
16 | "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b"
17 | },
18 | "dist": {
19 | "type": "zip",
20 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b",
21 | "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b",
22 | "shasum": ""
23 | },
24 | "require": {
25 | "php": "^7.1 || ^8.0"
26 | },
27 | "require-dev": {
28 | "doctrine/coding-standard": "^9 || ^11",
29 | "ext-pdo": "*",
30 | "ext-phar": "*",
31 | "phpbench/phpbench": "^0.16 || ^1",
32 | "phpstan/phpstan": "^1.4",
33 | "phpstan/phpstan-phpunit": "^1",
34 | "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
35 | "vimeo/psalm": "^4.30 || ^5.4"
36 | },
37 | "type": "library",
38 | "autoload": {
39 | "psr-4": {
40 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
41 | }
42 | },
43 | "notification-url": "https://packagist.org/downloads/",
44 | "license": [
45 | "MIT"
46 | ],
47 | "authors": [
48 | {
49 | "name": "Marco Pivetta",
50 | "email": "ocramius@gmail.com",
51 | "homepage": "https://ocramius.github.io/"
52 | }
53 | ],
54 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
55 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
56 | "keywords": [
57 | "constructor",
58 | "instantiate"
59 | ],
60 | "support": {
61 | "issues": "https://github.com/doctrine/instantiator/issues",
62 | "source": "https://github.com/doctrine/instantiator/tree/1.5.0"
63 | },
64 | "funding": [
65 | {
66 | "url": "https://www.doctrine-project.org/sponsorship.html",
67 | "type": "custom"
68 | },
69 | {
70 | "url": "https://www.patreon.com/phpdoctrine",
71 | "type": "patreon"
72 | },
73 | {
74 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
75 | "type": "tidelift"
76 | }
77 | ],
78 | "time": "2022-12-30T00:15:36+00:00"
79 | },
80 | {
81 | "name": "myclabs/deep-copy",
82 | "version": "1.11.1",
83 | "source": {
84 | "type": "git",
85 | "url": "https://github.com/myclabs/DeepCopy.git",
86 | "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c"
87 | },
88 | "dist": {
89 | "type": "zip",
90 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c",
91 | "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c",
92 | "shasum": ""
93 | },
94 | "require": {
95 | "php": "^7.1 || ^8.0"
96 | },
97 | "conflict": {
98 | "doctrine/collections": "<1.6.8",
99 | "doctrine/common": "<2.13.3 || >=3,<3.2.2"
100 | },
101 | "require-dev": {
102 | "doctrine/collections": "^1.6.8",
103 | "doctrine/common": "^2.13.3 || ^3.2.2",
104 | "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
105 | },
106 | "type": "library",
107 | "autoload": {
108 | "files": [
109 | "src/DeepCopy/deep_copy.php"
110 | ],
111 | "psr-4": {
112 | "DeepCopy\\": "src/DeepCopy/"
113 | }
114 | },
115 | "notification-url": "https://packagist.org/downloads/",
116 | "license": [
117 | "MIT"
118 | ],
119 | "description": "Create deep copies (clones) of your objects",
120 | "keywords": [
121 | "clone",
122 | "copy",
123 | "duplicate",
124 | "object",
125 | "object graph"
126 | ],
127 | "support": {
128 | "issues": "https://github.com/myclabs/DeepCopy/issues",
129 | "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1"
130 | },
131 | "funding": [
132 | {
133 | "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
134 | "type": "tidelift"
135 | }
136 | ],
137 | "time": "2023-03-08T13:26:56+00:00"
138 | },
139 | {
140 | "name": "nikic/php-parser",
141 | "version": "v4.16.0",
142 | "source": {
143 | "type": "git",
144 | "url": "https://github.com/nikic/PHP-Parser.git",
145 | "reference": "19526a33fb561ef417e822e85f08a00db4059c17"
146 | },
147 | "dist": {
148 | "type": "zip",
149 | "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17",
150 | "reference": "19526a33fb561ef417e822e85f08a00db4059c17",
151 | "shasum": ""
152 | },
153 | "require": {
154 | "ext-tokenizer": "*",
155 | "php": ">=7.0"
156 | },
157 | "require-dev": {
158 | "ircmaxell/php-yacc": "^0.0.7",
159 | "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
160 | },
161 | "bin": [
162 | "bin/php-parse"
163 | ],
164 | "type": "library",
165 | "extra": {
166 | "branch-alias": {
167 | "dev-master": "4.9-dev"
168 | }
169 | },
170 | "autoload": {
171 | "psr-4": {
172 | "PhpParser\\": "lib/PhpParser"
173 | }
174 | },
175 | "notification-url": "https://packagist.org/downloads/",
176 | "license": [
177 | "BSD-3-Clause"
178 | ],
179 | "authors": [
180 | {
181 | "name": "Nikita Popov"
182 | }
183 | ],
184 | "description": "A PHP parser written in PHP",
185 | "keywords": [
186 | "parser",
187 | "php"
188 | ],
189 | "support": {
190 | "issues": "https://github.com/nikic/PHP-Parser/issues",
191 | "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0"
192 | },
193 | "time": "2023-06-25T14:52:30+00:00"
194 | },
195 | {
196 | "name": "phar-io/manifest",
197 | "version": "2.0.3",
198 | "source": {
199 | "type": "git",
200 | "url": "https://github.com/phar-io/manifest.git",
201 | "reference": "97803eca37d319dfa7826cc2437fc020857acb53"
202 | },
203 | "dist": {
204 | "type": "zip",
205 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
206 | "reference": "97803eca37d319dfa7826cc2437fc020857acb53",
207 | "shasum": ""
208 | },
209 | "require": {
210 | "ext-dom": "*",
211 | "ext-phar": "*",
212 | "ext-xmlwriter": "*",
213 | "phar-io/version": "^3.0.1",
214 | "php": "^7.2 || ^8.0"
215 | },
216 | "type": "library",
217 | "extra": {
218 | "branch-alias": {
219 | "dev-master": "2.0.x-dev"
220 | }
221 | },
222 | "autoload": {
223 | "classmap": [
224 | "src/"
225 | ]
226 | },
227 | "notification-url": "https://packagist.org/downloads/",
228 | "license": [
229 | "BSD-3-Clause"
230 | ],
231 | "authors": [
232 | {
233 | "name": "Arne Blankerts",
234 | "email": "arne@blankerts.de",
235 | "role": "Developer"
236 | },
237 | {
238 | "name": "Sebastian Heuer",
239 | "email": "sebastian@phpeople.de",
240 | "role": "Developer"
241 | },
242 | {
243 | "name": "Sebastian Bergmann",
244 | "email": "sebastian@phpunit.de",
245 | "role": "Developer"
246 | }
247 | ],
248 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
249 | "support": {
250 | "issues": "https://github.com/phar-io/manifest/issues",
251 | "source": "https://github.com/phar-io/manifest/tree/2.0.3"
252 | },
253 | "time": "2021-07-20T11:28:43+00:00"
254 | },
255 | {
256 | "name": "phar-io/version",
257 | "version": "3.2.1",
258 | "source": {
259 | "type": "git",
260 | "url": "https://github.com/phar-io/version.git",
261 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
262 | },
263 | "dist": {
264 | "type": "zip",
265 | "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
266 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
267 | "shasum": ""
268 | },
269 | "require": {
270 | "php": "^7.2 || ^8.0"
271 | },
272 | "type": "library",
273 | "autoload": {
274 | "classmap": [
275 | "src/"
276 | ]
277 | },
278 | "notification-url": "https://packagist.org/downloads/",
279 | "license": [
280 | "BSD-3-Clause"
281 | ],
282 | "authors": [
283 | {
284 | "name": "Arne Blankerts",
285 | "email": "arne@blankerts.de",
286 | "role": "Developer"
287 | },
288 | {
289 | "name": "Sebastian Heuer",
290 | "email": "sebastian@phpeople.de",
291 | "role": "Developer"
292 | },
293 | {
294 | "name": "Sebastian Bergmann",
295 | "email": "sebastian@phpunit.de",
296 | "role": "Developer"
297 | }
298 | ],
299 | "description": "Library for handling version information and constraints",
300 | "support": {
301 | "issues": "https://github.com/phar-io/version/issues",
302 | "source": "https://github.com/phar-io/version/tree/3.2.1"
303 | },
304 | "time": "2022-02-21T01:04:05+00:00"
305 | },
306 | {
307 | "name": "phpunit/php-code-coverage",
308 | "version": "9.2.27",
309 | "source": {
310 | "type": "git",
311 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
312 | "reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1"
313 | },
314 | "dist": {
315 | "type": "zip",
316 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/b0a88255cb70d52653d80c890bd7f38740ea50d1",
317 | "reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1",
318 | "shasum": ""
319 | },
320 | "require": {
321 | "ext-dom": "*",
322 | "ext-libxml": "*",
323 | "ext-xmlwriter": "*",
324 | "nikic/php-parser": "^4.15",
325 | "php": ">=7.3",
326 | "phpunit/php-file-iterator": "^3.0.3",
327 | "phpunit/php-text-template": "^2.0.2",
328 | "sebastian/code-unit-reverse-lookup": "^2.0.2",
329 | "sebastian/complexity": "^2.0",
330 | "sebastian/environment": "^5.1.2",
331 | "sebastian/lines-of-code": "^1.0.3",
332 | "sebastian/version": "^3.0.1",
333 | "theseer/tokenizer": "^1.2.0"
334 | },
335 | "require-dev": {
336 | "phpunit/phpunit": "^9.3"
337 | },
338 | "suggest": {
339 | "ext-pcov": "PHP extension that provides line coverage",
340 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage"
341 | },
342 | "type": "library",
343 | "extra": {
344 | "branch-alias": {
345 | "dev-master": "9.2-dev"
346 | }
347 | },
348 | "autoload": {
349 | "classmap": [
350 | "src/"
351 | ]
352 | },
353 | "notification-url": "https://packagist.org/downloads/",
354 | "license": [
355 | "BSD-3-Clause"
356 | ],
357 | "authors": [
358 | {
359 | "name": "Sebastian Bergmann",
360 | "email": "sebastian@phpunit.de",
361 | "role": "lead"
362 | }
363 | ],
364 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
365 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
366 | "keywords": [
367 | "coverage",
368 | "testing",
369 | "xunit"
370 | ],
371 | "support": {
372 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
373 | "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
374 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.27"
375 | },
376 | "funding": [
377 | {
378 | "url": "https://github.com/sebastianbergmann",
379 | "type": "github"
380 | }
381 | ],
382 | "time": "2023-07-26T13:44:30+00:00"
383 | },
384 | {
385 | "name": "phpunit/php-file-iterator",
386 | "version": "3.0.6",
387 | "source": {
388 | "type": "git",
389 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
390 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
391 | },
392 | "dist": {
393 | "type": "zip",
394 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
395 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
396 | "shasum": ""
397 | },
398 | "require": {
399 | "php": ">=7.3"
400 | },
401 | "require-dev": {
402 | "phpunit/phpunit": "^9.3"
403 | },
404 | "type": "library",
405 | "extra": {
406 | "branch-alias": {
407 | "dev-master": "3.0-dev"
408 | }
409 | },
410 | "autoload": {
411 | "classmap": [
412 | "src/"
413 | ]
414 | },
415 | "notification-url": "https://packagist.org/downloads/",
416 | "license": [
417 | "BSD-3-Clause"
418 | ],
419 | "authors": [
420 | {
421 | "name": "Sebastian Bergmann",
422 | "email": "sebastian@phpunit.de",
423 | "role": "lead"
424 | }
425 | ],
426 | "description": "FilterIterator implementation that filters files based on a list of suffixes.",
427 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
428 | "keywords": [
429 | "filesystem",
430 | "iterator"
431 | ],
432 | "support": {
433 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
434 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
435 | },
436 | "funding": [
437 | {
438 | "url": "https://github.com/sebastianbergmann",
439 | "type": "github"
440 | }
441 | ],
442 | "time": "2021-12-02T12:48:52+00:00"
443 | },
444 | {
445 | "name": "phpunit/php-invoker",
446 | "version": "3.1.1",
447 | "source": {
448 | "type": "git",
449 | "url": "https://github.com/sebastianbergmann/php-invoker.git",
450 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
451 | },
452 | "dist": {
453 | "type": "zip",
454 | "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
455 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
456 | "shasum": ""
457 | },
458 | "require": {
459 | "php": ">=7.3"
460 | },
461 | "require-dev": {
462 | "ext-pcntl": "*",
463 | "phpunit/phpunit": "^9.3"
464 | },
465 | "suggest": {
466 | "ext-pcntl": "*"
467 | },
468 | "type": "library",
469 | "extra": {
470 | "branch-alias": {
471 | "dev-master": "3.1-dev"
472 | }
473 | },
474 | "autoload": {
475 | "classmap": [
476 | "src/"
477 | ]
478 | },
479 | "notification-url": "https://packagist.org/downloads/",
480 | "license": [
481 | "BSD-3-Clause"
482 | ],
483 | "authors": [
484 | {
485 | "name": "Sebastian Bergmann",
486 | "email": "sebastian@phpunit.de",
487 | "role": "lead"
488 | }
489 | ],
490 | "description": "Invoke callables with a timeout",
491 | "homepage": "https://github.com/sebastianbergmann/php-invoker/",
492 | "keywords": [
493 | "process"
494 | ],
495 | "support": {
496 | "issues": "https://github.com/sebastianbergmann/php-invoker/issues",
497 | "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
498 | },
499 | "funding": [
500 | {
501 | "url": "https://github.com/sebastianbergmann",
502 | "type": "github"
503 | }
504 | ],
505 | "time": "2020-09-28T05:58:55+00:00"
506 | },
507 | {
508 | "name": "phpunit/php-text-template",
509 | "version": "2.0.4",
510 | "source": {
511 | "type": "git",
512 | "url": "https://github.com/sebastianbergmann/php-text-template.git",
513 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
514 | },
515 | "dist": {
516 | "type": "zip",
517 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
518 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
519 | "shasum": ""
520 | },
521 | "require": {
522 | "php": ">=7.3"
523 | },
524 | "require-dev": {
525 | "phpunit/phpunit": "^9.3"
526 | },
527 | "type": "library",
528 | "extra": {
529 | "branch-alias": {
530 | "dev-master": "2.0-dev"
531 | }
532 | },
533 | "autoload": {
534 | "classmap": [
535 | "src/"
536 | ]
537 | },
538 | "notification-url": "https://packagist.org/downloads/",
539 | "license": [
540 | "BSD-3-Clause"
541 | ],
542 | "authors": [
543 | {
544 | "name": "Sebastian Bergmann",
545 | "email": "sebastian@phpunit.de",
546 | "role": "lead"
547 | }
548 | ],
549 | "description": "Simple template engine.",
550 | "homepage": "https://github.com/sebastianbergmann/php-text-template/",
551 | "keywords": [
552 | "template"
553 | ],
554 | "support": {
555 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
556 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
557 | },
558 | "funding": [
559 | {
560 | "url": "https://github.com/sebastianbergmann",
561 | "type": "github"
562 | }
563 | ],
564 | "time": "2020-10-26T05:33:50+00:00"
565 | },
566 | {
567 | "name": "phpunit/php-timer",
568 | "version": "5.0.3",
569 | "source": {
570 | "type": "git",
571 | "url": "https://github.com/sebastianbergmann/php-timer.git",
572 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
573 | },
574 | "dist": {
575 | "type": "zip",
576 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
577 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
578 | "shasum": ""
579 | },
580 | "require": {
581 | "php": ">=7.3"
582 | },
583 | "require-dev": {
584 | "phpunit/phpunit": "^9.3"
585 | },
586 | "type": "library",
587 | "extra": {
588 | "branch-alias": {
589 | "dev-master": "5.0-dev"
590 | }
591 | },
592 | "autoload": {
593 | "classmap": [
594 | "src/"
595 | ]
596 | },
597 | "notification-url": "https://packagist.org/downloads/",
598 | "license": [
599 | "BSD-3-Clause"
600 | ],
601 | "authors": [
602 | {
603 | "name": "Sebastian Bergmann",
604 | "email": "sebastian@phpunit.de",
605 | "role": "lead"
606 | }
607 | ],
608 | "description": "Utility class for timing",
609 | "homepage": "https://github.com/sebastianbergmann/php-timer/",
610 | "keywords": [
611 | "timer"
612 | ],
613 | "support": {
614 | "issues": "https://github.com/sebastianbergmann/php-timer/issues",
615 | "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
616 | },
617 | "funding": [
618 | {
619 | "url": "https://github.com/sebastianbergmann",
620 | "type": "github"
621 | }
622 | ],
623 | "time": "2020-10-26T13:16:10+00:00"
624 | },
625 | {
626 | "name": "phpunit/phpunit",
627 | "version": "9.6.10",
628 | "source": {
629 | "type": "git",
630 | "url": "https://github.com/sebastianbergmann/phpunit.git",
631 | "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328"
632 | },
633 | "dist": {
634 | "type": "zip",
635 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a6d351645c3fe5a30f5e86be6577d946af65a328",
636 | "reference": "a6d351645c3fe5a30f5e86be6577d946af65a328",
637 | "shasum": ""
638 | },
639 | "require": {
640 | "doctrine/instantiator": "^1.3.1 || ^2",
641 | "ext-dom": "*",
642 | "ext-json": "*",
643 | "ext-libxml": "*",
644 | "ext-mbstring": "*",
645 | "ext-xml": "*",
646 | "ext-xmlwriter": "*",
647 | "myclabs/deep-copy": "^1.10.1",
648 | "phar-io/manifest": "^2.0.3",
649 | "phar-io/version": "^3.0.2",
650 | "php": ">=7.3",
651 | "phpunit/php-code-coverage": "^9.2.13",
652 | "phpunit/php-file-iterator": "^3.0.5",
653 | "phpunit/php-invoker": "^3.1.1",
654 | "phpunit/php-text-template": "^2.0.3",
655 | "phpunit/php-timer": "^5.0.2",
656 | "sebastian/cli-parser": "^1.0.1",
657 | "sebastian/code-unit": "^1.0.6",
658 | "sebastian/comparator": "^4.0.8",
659 | "sebastian/diff": "^4.0.3",
660 | "sebastian/environment": "^5.1.3",
661 | "sebastian/exporter": "^4.0.5",
662 | "sebastian/global-state": "^5.0.1",
663 | "sebastian/object-enumerator": "^4.0.3",
664 | "sebastian/resource-operations": "^3.0.3",
665 | "sebastian/type": "^3.2",
666 | "sebastian/version": "^3.0.2"
667 | },
668 | "suggest": {
669 | "ext-soap": "To be able to generate mocks based on WSDL files",
670 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage"
671 | },
672 | "bin": [
673 | "phpunit"
674 | ],
675 | "type": "library",
676 | "extra": {
677 | "branch-alias": {
678 | "dev-master": "9.6-dev"
679 | }
680 | },
681 | "autoload": {
682 | "files": [
683 | "src/Framework/Assert/Functions.php"
684 | ],
685 | "classmap": [
686 | "src/"
687 | ]
688 | },
689 | "notification-url": "https://packagist.org/downloads/",
690 | "license": [
691 | "BSD-3-Clause"
692 | ],
693 | "authors": [
694 | {
695 | "name": "Sebastian Bergmann",
696 | "email": "sebastian@phpunit.de",
697 | "role": "lead"
698 | }
699 | ],
700 | "description": "The PHP Unit Testing framework.",
701 | "homepage": "https://phpunit.de/",
702 | "keywords": [
703 | "phpunit",
704 | "testing",
705 | "xunit"
706 | ],
707 | "support": {
708 | "issues": "https://github.com/sebastianbergmann/phpunit/issues",
709 | "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
710 | "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.10"
711 | },
712 | "funding": [
713 | {
714 | "url": "https://phpunit.de/sponsors.html",
715 | "type": "custom"
716 | },
717 | {
718 | "url": "https://github.com/sebastianbergmann",
719 | "type": "github"
720 | },
721 | {
722 | "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
723 | "type": "tidelift"
724 | }
725 | ],
726 | "time": "2023-07-10T04:04:23+00:00"
727 | },
728 | {
729 | "name": "sebastian/cli-parser",
730 | "version": "1.0.1",
731 | "source": {
732 | "type": "git",
733 | "url": "https://github.com/sebastianbergmann/cli-parser.git",
734 | "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
735 | },
736 | "dist": {
737 | "type": "zip",
738 | "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
739 | "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
740 | "shasum": ""
741 | },
742 | "require": {
743 | "php": ">=7.3"
744 | },
745 | "require-dev": {
746 | "phpunit/phpunit": "^9.3"
747 | },
748 | "type": "library",
749 | "extra": {
750 | "branch-alias": {
751 | "dev-master": "1.0-dev"
752 | }
753 | },
754 | "autoload": {
755 | "classmap": [
756 | "src/"
757 | ]
758 | },
759 | "notification-url": "https://packagist.org/downloads/",
760 | "license": [
761 | "BSD-3-Clause"
762 | ],
763 | "authors": [
764 | {
765 | "name": "Sebastian Bergmann",
766 | "email": "sebastian@phpunit.de",
767 | "role": "lead"
768 | }
769 | ],
770 | "description": "Library for parsing CLI options",
771 | "homepage": "https://github.com/sebastianbergmann/cli-parser",
772 | "support": {
773 | "issues": "https://github.com/sebastianbergmann/cli-parser/issues",
774 | "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
775 | },
776 | "funding": [
777 | {
778 | "url": "https://github.com/sebastianbergmann",
779 | "type": "github"
780 | }
781 | ],
782 | "time": "2020-09-28T06:08:49+00:00"
783 | },
784 | {
785 | "name": "sebastian/code-unit",
786 | "version": "1.0.8",
787 | "source": {
788 | "type": "git",
789 | "url": "https://github.com/sebastianbergmann/code-unit.git",
790 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
791 | },
792 | "dist": {
793 | "type": "zip",
794 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
795 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
796 | "shasum": ""
797 | },
798 | "require": {
799 | "php": ">=7.3"
800 | },
801 | "require-dev": {
802 | "phpunit/phpunit": "^9.3"
803 | },
804 | "type": "library",
805 | "extra": {
806 | "branch-alias": {
807 | "dev-master": "1.0-dev"
808 | }
809 | },
810 | "autoload": {
811 | "classmap": [
812 | "src/"
813 | ]
814 | },
815 | "notification-url": "https://packagist.org/downloads/",
816 | "license": [
817 | "BSD-3-Clause"
818 | ],
819 | "authors": [
820 | {
821 | "name": "Sebastian Bergmann",
822 | "email": "sebastian@phpunit.de",
823 | "role": "lead"
824 | }
825 | ],
826 | "description": "Collection of value objects that represent the PHP code units",
827 | "homepage": "https://github.com/sebastianbergmann/code-unit",
828 | "support": {
829 | "issues": "https://github.com/sebastianbergmann/code-unit/issues",
830 | "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
831 | },
832 | "funding": [
833 | {
834 | "url": "https://github.com/sebastianbergmann",
835 | "type": "github"
836 | }
837 | ],
838 | "time": "2020-10-26T13:08:54+00:00"
839 | },
840 | {
841 | "name": "sebastian/code-unit-reverse-lookup",
842 | "version": "2.0.3",
843 | "source": {
844 | "type": "git",
845 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
846 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
847 | },
848 | "dist": {
849 | "type": "zip",
850 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
851 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
852 | "shasum": ""
853 | },
854 | "require": {
855 | "php": ">=7.3"
856 | },
857 | "require-dev": {
858 | "phpunit/phpunit": "^9.3"
859 | },
860 | "type": "library",
861 | "extra": {
862 | "branch-alias": {
863 | "dev-master": "2.0-dev"
864 | }
865 | },
866 | "autoload": {
867 | "classmap": [
868 | "src/"
869 | ]
870 | },
871 | "notification-url": "https://packagist.org/downloads/",
872 | "license": [
873 | "BSD-3-Clause"
874 | ],
875 | "authors": [
876 | {
877 | "name": "Sebastian Bergmann",
878 | "email": "sebastian@phpunit.de"
879 | }
880 | ],
881 | "description": "Looks up which function or method a line of code belongs to",
882 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
883 | "support": {
884 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
885 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
886 | },
887 | "funding": [
888 | {
889 | "url": "https://github.com/sebastianbergmann",
890 | "type": "github"
891 | }
892 | ],
893 | "time": "2020-09-28T05:30:19+00:00"
894 | },
895 | {
896 | "name": "sebastian/comparator",
897 | "version": "4.0.8",
898 | "source": {
899 | "type": "git",
900 | "url": "https://github.com/sebastianbergmann/comparator.git",
901 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a"
902 | },
903 | "dist": {
904 | "type": "zip",
905 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
906 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a",
907 | "shasum": ""
908 | },
909 | "require": {
910 | "php": ">=7.3",
911 | "sebastian/diff": "^4.0",
912 | "sebastian/exporter": "^4.0"
913 | },
914 | "require-dev": {
915 | "phpunit/phpunit": "^9.3"
916 | },
917 | "type": "library",
918 | "extra": {
919 | "branch-alias": {
920 | "dev-master": "4.0-dev"
921 | }
922 | },
923 | "autoload": {
924 | "classmap": [
925 | "src/"
926 | ]
927 | },
928 | "notification-url": "https://packagist.org/downloads/",
929 | "license": [
930 | "BSD-3-Clause"
931 | ],
932 | "authors": [
933 | {
934 | "name": "Sebastian Bergmann",
935 | "email": "sebastian@phpunit.de"
936 | },
937 | {
938 | "name": "Jeff Welch",
939 | "email": "whatthejeff@gmail.com"
940 | },
941 | {
942 | "name": "Volker Dusch",
943 | "email": "github@wallbash.com"
944 | },
945 | {
946 | "name": "Bernhard Schussek",
947 | "email": "bschussek@2bepublished.at"
948 | }
949 | ],
950 | "description": "Provides the functionality to compare PHP values for equality",
951 | "homepage": "https://github.com/sebastianbergmann/comparator",
952 | "keywords": [
953 | "comparator",
954 | "compare",
955 | "equality"
956 | ],
957 | "support": {
958 | "issues": "https://github.com/sebastianbergmann/comparator/issues",
959 | "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
960 | },
961 | "funding": [
962 | {
963 | "url": "https://github.com/sebastianbergmann",
964 | "type": "github"
965 | }
966 | ],
967 | "time": "2022-09-14T12:41:17+00:00"
968 | },
969 | {
970 | "name": "sebastian/complexity",
971 | "version": "2.0.2",
972 | "source": {
973 | "type": "git",
974 | "url": "https://github.com/sebastianbergmann/complexity.git",
975 | "reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
976 | },
977 | "dist": {
978 | "type": "zip",
979 | "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
980 | "reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
981 | "shasum": ""
982 | },
983 | "require": {
984 | "nikic/php-parser": "^4.7",
985 | "php": ">=7.3"
986 | },
987 | "require-dev": {
988 | "phpunit/phpunit": "^9.3"
989 | },
990 | "type": "library",
991 | "extra": {
992 | "branch-alias": {
993 | "dev-master": "2.0-dev"
994 | }
995 | },
996 | "autoload": {
997 | "classmap": [
998 | "src/"
999 | ]
1000 | },
1001 | "notification-url": "https://packagist.org/downloads/",
1002 | "license": [
1003 | "BSD-3-Clause"
1004 | ],
1005 | "authors": [
1006 | {
1007 | "name": "Sebastian Bergmann",
1008 | "email": "sebastian@phpunit.de",
1009 | "role": "lead"
1010 | }
1011 | ],
1012 | "description": "Library for calculating the complexity of PHP code units",
1013 | "homepage": "https://github.com/sebastianbergmann/complexity",
1014 | "support": {
1015 | "issues": "https://github.com/sebastianbergmann/complexity/issues",
1016 | "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2"
1017 | },
1018 | "funding": [
1019 | {
1020 | "url": "https://github.com/sebastianbergmann",
1021 | "type": "github"
1022 | }
1023 | ],
1024 | "time": "2020-10-26T15:52:27+00:00"
1025 | },
1026 | {
1027 | "name": "sebastian/diff",
1028 | "version": "4.0.5",
1029 | "source": {
1030 | "type": "git",
1031 | "url": "https://github.com/sebastianbergmann/diff.git",
1032 | "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131"
1033 | },
1034 | "dist": {
1035 | "type": "zip",
1036 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131",
1037 | "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131",
1038 | "shasum": ""
1039 | },
1040 | "require": {
1041 | "php": ">=7.3"
1042 | },
1043 | "require-dev": {
1044 | "phpunit/phpunit": "^9.3",
1045 | "symfony/process": "^4.2 || ^5"
1046 | },
1047 | "type": "library",
1048 | "extra": {
1049 | "branch-alias": {
1050 | "dev-master": "4.0-dev"
1051 | }
1052 | },
1053 | "autoload": {
1054 | "classmap": [
1055 | "src/"
1056 | ]
1057 | },
1058 | "notification-url": "https://packagist.org/downloads/",
1059 | "license": [
1060 | "BSD-3-Clause"
1061 | ],
1062 | "authors": [
1063 | {
1064 | "name": "Sebastian Bergmann",
1065 | "email": "sebastian@phpunit.de"
1066 | },
1067 | {
1068 | "name": "Kore Nordmann",
1069 | "email": "mail@kore-nordmann.de"
1070 | }
1071 | ],
1072 | "description": "Diff implementation",
1073 | "homepage": "https://github.com/sebastianbergmann/diff",
1074 | "keywords": [
1075 | "diff",
1076 | "udiff",
1077 | "unidiff",
1078 | "unified diff"
1079 | ],
1080 | "support": {
1081 | "issues": "https://github.com/sebastianbergmann/diff/issues",
1082 | "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5"
1083 | },
1084 | "funding": [
1085 | {
1086 | "url": "https://github.com/sebastianbergmann",
1087 | "type": "github"
1088 | }
1089 | ],
1090 | "time": "2023-05-07T05:35:17+00:00"
1091 | },
1092 | {
1093 | "name": "sebastian/environment",
1094 | "version": "5.1.5",
1095 | "source": {
1096 | "type": "git",
1097 | "url": "https://github.com/sebastianbergmann/environment.git",
1098 | "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed"
1099 | },
1100 | "dist": {
1101 | "type": "zip",
1102 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed",
1103 | "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed",
1104 | "shasum": ""
1105 | },
1106 | "require": {
1107 | "php": ">=7.3"
1108 | },
1109 | "require-dev": {
1110 | "phpunit/phpunit": "^9.3"
1111 | },
1112 | "suggest": {
1113 | "ext-posix": "*"
1114 | },
1115 | "type": "library",
1116 | "extra": {
1117 | "branch-alias": {
1118 | "dev-master": "5.1-dev"
1119 | }
1120 | },
1121 | "autoload": {
1122 | "classmap": [
1123 | "src/"
1124 | ]
1125 | },
1126 | "notification-url": "https://packagist.org/downloads/",
1127 | "license": [
1128 | "BSD-3-Clause"
1129 | ],
1130 | "authors": [
1131 | {
1132 | "name": "Sebastian Bergmann",
1133 | "email": "sebastian@phpunit.de"
1134 | }
1135 | ],
1136 | "description": "Provides functionality to handle HHVM/PHP environments",
1137 | "homepage": "http://www.github.com/sebastianbergmann/environment",
1138 | "keywords": [
1139 | "Xdebug",
1140 | "environment",
1141 | "hhvm"
1142 | ],
1143 | "support": {
1144 | "issues": "https://github.com/sebastianbergmann/environment/issues",
1145 | "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5"
1146 | },
1147 | "funding": [
1148 | {
1149 | "url": "https://github.com/sebastianbergmann",
1150 | "type": "github"
1151 | }
1152 | ],
1153 | "time": "2023-02-03T06:03:51+00:00"
1154 | },
1155 | {
1156 | "name": "sebastian/exporter",
1157 | "version": "4.0.5",
1158 | "source": {
1159 | "type": "git",
1160 | "url": "https://github.com/sebastianbergmann/exporter.git",
1161 | "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
1162 | },
1163 | "dist": {
1164 | "type": "zip",
1165 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
1166 | "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
1167 | "shasum": ""
1168 | },
1169 | "require": {
1170 | "php": ">=7.3",
1171 | "sebastian/recursion-context": "^4.0"
1172 | },
1173 | "require-dev": {
1174 | "ext-mbstring": "*",
1175 | "phpunit/phpunit": "^9.3"
1176 | },
1177 | "type": "library",
1178 | "extra": {
1179 | "branch-alias": {
1180 | "dev-master": "4.0-dev"
1181 | }
1182 | },
1183 | "autoload": {
1184 | "classmap": [
1185 | "src/"
1186 | ]
1187 | },
1188 | "notification-url": "https://packagist.org/downloads/",
1189 | "license": [
1190 | "BSD-3-Clause"
1191 | ],
1192 | "authors": [
1193 | {
1194 | "name": "Sebastian Bergmann",
1195 | "email": "sebastian@phpunit.de"
1196 | },
1197 | {
1198 | "name": "Jeff Welch",
1199 | "email": "whatthejeff@gmail.com"
1200 | },
1201 | {
1202 | "name": "Volker Dusch",
1203 | "email": "github@wallbash.com"
1204 | },
1205 | {
1206 | "name": "Adam Harvey",
1207 | "email": "aharvey@php.net"
1208 | },
1209 | {
1210 | "name": "Bernhard Schussek",
1211 | "email": "bschussek@gmail.com"
1212 | }
1213 | ],
1214 | "description": "Provides the functionality to export PHP variables for visualization",
1215 | "homepage": "https://www.github.com/sebastianbergmann/exporter",
1216 | "keywords": [
1217 | "export",
1218 | "exporter"
1219 | ],
1220 | "support": {
1221 | "issues": "https://github.com/sebastianbergmann/exporter/issues",
1222 | "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
1223 | },
1224 | "funding": [
1225 | {
1226 | "url": "https://github.com/sebastianbergmann",
1227 | "type": "github"
1228 | }
1229 | ],
1230 | "time": "2022-09-14T06:03:37+00:00"
1231 | },
1232 | {
1233 | "name": "sebastian/global-state",
1234 | "version": "5.0.6",
1235 | "source": {
1236 | "type": "git",
1237 | "url": "https://github.com/sebastianbergmann/global-state.git",
1238 | "reference": "bde739e7565280bda77be70044ac1047bc007e34"
1239 | },
1240 | "dist": {
1241 | "type": "zip",
1242 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34",
1243 | "reference": "bde739e7565280bda77be70044ac1047bc007e34",
1244 | "shasum": ""
1245 | },
1246 | "require": {
1247 | "php": ">=7.3",
1248 | "sebastian/object-reflector": "^2.0",
1249 | "sebastian/recursion-context": "^4.0"
1250 | },
1251 | "require-dev": {
1252 | "ext-dom": "*",
1253 | "phpunit/phpunit": "^9.3"
1254 | },
1255 | "suggest": {
1256 | "ext-uopz": "*"
1257 | },
1258 | "type": "library",
1259 | "extra": {
1260 | "branch-alias": {
1261 | "dev-master": "5.0-dev"
1262 | }
1263 | },
1264 | "autoload": {
1265 | "classmap": [
1266 | "src/"
1267 | ]
1268 | },
1269 | "notification-url": "https://packagist.org/downloads/",
1270 | "license": [
1271 | "BSD-3-Clause"
1272 | ],
1273 | "authors": [
1274 | {
1275 | "name": "Sebastian Bergmann",
1276 | "email": "sebastian@phpunit.de"
1277 | }
1278 | ],
1279 | "description": "Snapshotting of global state",
1280 | "homepage": "http://www.github.com/sebastianbergmann/global-state",
1281 | "keywords": [
1282 | "global state"
1283 | ],
1284 | "support": {
1285 | "issues": "https://github.com/sebastianbergmann/global-state/issues",
1286 | "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6"
1287 | },
1288 | "funding": [
1289 | {
1290 | "url": "https://github.com/sebastianbergmann",
1291 | "type": "github"
1292 | }
1293 | ],
1294 | "time": "2023-08-02T09:26:13+00:00"
1295 | },
1296 | {
1297 | "name": "sebastian/lines-of-code",
1298 | "version": "1.0.3",
1299 | "source": {
1300 | "type": "git",
1301 | "url": "https://github.com/sebastianbergmann/lines-of-code.git",
1302 | "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
1303 | },
1304 | "dist": {
1305 | "type": "zip",
1306 | "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
1307 | "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
1308 | "shasum": ""
1309 | },
1310 | "require": {
1311 | "nikic/php-parser": "^4.6",
1312 | "php": ">=7.3"
1313 | },
1314 | "require-dev": {
1315 | "phpunit/phpunit": "^9.3"
1316 | },
1317 | "type": "library",
1318 | "extra": {
1319 | "branch-alias": {
1320 | "dev-master": "1.0-dev"
1321 | }
1322 | },
1323 | "autoload": {
1324 | "classmap": [
1325 | "src/"
1326 | ]
1327 | },
1328 | "notification-url": "https://packagist.org/downloads/",
1329 | "license": [
1330 | "BSD-3-Clause"
1331 | ],
1332 | "authors": [
1333 | {
1334 | "name": "Sebastian Bergmann",
1335 | "email": "sebastian@phpunit.de",
1336 | "role": "lead"
1337 | }
1338 | ],
1339 | "description": "Library for counting the lines of code in PHP source code",
1340 | "homepage": "https://github.com/sebastianbergmann/lines-of-code",
1341 | "support": {
1342 | "issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
1343 | "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
1344 | },
1345 | "funding": [
1346 | {
1347 | "url": "https://github.com/sebastianbergmann",
1348 | "type": "github"
1349 | }
1350 | ],
1351 | "time": "2020-11-28T06:42:11+00:00"
1352 | },
1353 | {
1354 | "name": "sebastian/object-enumerator",
1355 | "version": "4.0.4",
1356 | "source": {
1357 | "type": "git",
1358 | "url": "https://github.com/sebastianbergmann/object-enumerator.git",
1359 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
1360 | },
1361 | "dist": {
1362 | "type": "zip",
1363 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
1364 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
1365 | "shasum": ""
1366 | },
1367 | "require": {
1368 | "php": ">=7.3",
1369 | "sebastian/object-reflector": "^2.0",
1370 | "sebastian/recursion-context": "^4.0"
1371 | },
1372 | "require-dev": {
1373 | "phpunit/phpunit": "^9.3"
1374 | },
1375 | "type": "library",
1376 | "extra": {
1377 | "branch-alias": {
1378 | "dev-master": "4.0-dev"
1379 | }
1380 | },
1381 | "autoload": {
1382 | "classmap": [
1383 | "src/"
1384 | ]
1385 | },
1386 | "notification-url": "https://packagist.org/downloads/",
1387 | "license": [
1388 | "BSD-3-Clause"
1389 | ],
1390 | "authors": [
1391 | {
1392 | "name": "Sebastian Bergmann",
1393 | "email": "sebastian@phpunit.de"
1394 | }
1395 | ],
1396 | "description": "Traverses array structures and object graphs to enumerate all referenced objects",
1397 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
1398 | "support": {
1399 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
1400 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4"
1401 | },
1402 | "funding": [
1403 | {
1404 | "url": "https://github.com/sebastianbergmann",
1405 | "type": "github"
1406 | }
1407 | ],
1408 | "time": "2020-10-26T13:12:34+00:00"
1409 | },
1410 | {
1411 | "name": "sebastian/object-reflector",
1412 | "version": "2.0.4",
1413 | "source": {
1414 | "type": "git",
1415 | "url": "https://github.com/sebastianbergmann/object-reflector.git",
1416 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
1417 | },
1418 | "dist": {
1419 | "type": "zip",
1420 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
1421 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
1422 | "shasum": ""
1423 | },
1424 | "require": {
1425 | "php": ">=7.3"
1426 | },
1427 | "require-dev": {
1428 | "phpunit/phpunit": "^9.3"
1429 | },
1430 | "type": "library",
1431 | "extra": {
1432 | "branch-alias": {
1433 | "dev-master": "2.0-dev"
1434 | }
1435 | },
1436 | "autoload": {
1437 | "classmap": [
1438 | "src/"
1439 | ]
1440 | },
1441 | "notification-url": "https://packagist.org/downloads/",
1442 | "license": [
1443 | "BSD-3-Clause"
1444 | ],
1445 | "authors": [
1446 | {
1447 | "name": "Sebastian Bergmann",
1448 | "email": "sebastian@phpunit.de"
1449 | }
1450 | ],
1451 | "description": "Allows reflection of object attributes, including inherited and non-public ones",
1452 | "homepage": "https://github.com/sebastianbergmann/object-reflector/",
1453 | "support": {
1454 | "issues": "https://github.com/sebastianbergmann/object-reflector/issues",
1455 | "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
1456 | },
1457 | "funding": [
1458 | {
1459 | "url": "https://github.com/sebastianbergmann",
1460 | "type": "github"
1461 | }
1462 | ],
1463 | "time": "2020-10-26T13:14:26+00:00"
1464 | },
1465 | {
1466 | "name": "sebastian/recursion-context",
1467 | "version": "4.0.5",
1468 | "source": {
1469 | "type": "git",
1470 | "url": "https://github.com/sebastianbergmann/recursion-context.git",
1471 | "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1"
1472 | },
1473 | "dist": {
1474 | "type": "zip",
1475 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1",
1476 | "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1",
1477 | "shasum": ""
1478 | },
1479 | "require": {
1480 | "php": ">=7.3"
1481 | },
1482 | "require-dev": {
1483 | "phpunit/phpunit": "^9.3"
1484 | },
1485 | "type": "library",
1486 | "extra": {
1487 | "branch-alias": {
1488 | "dev-master": "4.0-dev"
1489 | }
1490 | },
1491 | "autoload": {
1492 | "classmap": [
1493 | "src/"
1494 | ]
1495 | },
1496 | "notification-url": "https://packagist.org/downloads/",
1497 | "license": [
1498 | "BSD-3-Clause"
1499 | ],
1500 | "authors": [
1501 | {
1502 | "name": "Sebastian Bergmann",
1503 | "email": "sebastian@phpunit.de"
1504 | },
1505 | {
1506 | "name": "Jeff Welch",
1507 | "email": "whatthejeff@gmail.com"
1508 | },
1509 | {
1510 | "name": "Adam Harvey",
1511 | "email": "aharvey@php.net"
1512 | }
1513 | ],
1514 | "description": "Provides functionality to recursively process PHP variables",
1515 | "homepage": "https://github.com/sebastianbergmann/recursion-context",
1516 | "support": {
1517 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues",
1518 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5"
1519 | },
1520 | "funding": [
1521 | {
1522 | "url": "https://github.com/sebastianbergmann",
1523 | "type": "github"
1524 | }
1525 | ],
1526 | "time": "2023-02-03T06:07:39+00:00"
1527 | },
1528 | {
1529 | "name": "sebastian/resource-operations",
1530 | "version": "3.0.3",
1531 | "source": {
1532 | "type": "git",
1533 | "url": "https://github.com/sebastianbergmann/resource-operations.git",
1534 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
1535 | },
1536 | "dist": {
1537 | "type": "zip",
1538 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
1539 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
1540 | "shasum": ""
1541 | },
1542 | "require": {
1543 | "php": ">=7.3"
1544 | },
1545 | "require-dev": {
1546 | "phpunit/phpunit": "^9.0"
1547 | },
1548 | "type": "library",
1549 | "extra": {
1550 | "branch-alias": {
1551 | "dev-master": "3.0-dev"
1552 | }
1553 | },
1554 | "autoload": {
1555 | "classmap": [
1556 | "src/"
1557 | ]
1558 | },
1559 | "notification-url": "https://packagist.org/downloads/",
1560 | "license": [
1561 | "BSD-3-Clause"
1562 | ],
1563 | "authors": [
1564 | {
1565 | "name": "Sebastian Bergmann",
1566 | "email": "sebastian@phpunit.de"
1567 | }
1568 | ],
1569 | "description": "Provides a list of PHP built-in functions that operate on resources",
1570 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
1571 | "support": {
1572 | "issues": "https://github.com/sebastianbergmann/resource-operations/issues",
1573 | "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
1574 | },
1575 | "funding": [
1576 | {
1577 | "url": "https://github.com/sebastianbergmann",
1578 | "type": "github"
1579 | }
1580 | ],
1581 | "time": "2020-09-28T06:45:17+00:00"
1582 | },
1583 | {
1584 | "name": "sebastian/type",
1585 | "version": "3.2.1",
1586 | "source": {
1587 | "type": "git",
1588 | "url": "https://github.com/sebastianbergmann/type.git",
1589 | "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7"
1590 | },
1591 | "dist": {
1592 | "type": "zip",
1593 | "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7",
1594 | "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7",
1595 | "shasum": ""
1596 | },
1597 | "require": {
1598 | "php": ">=7.3"
1599 | },
1600 | "require-dev": {
1601 | "phpunit/phpunit": "^9.5"
1602 | },
1603 | "type": "library",
1604 | "extra": {
1605 | "branch-alias": {
1606 | "dev-master": "3.2-dev"
1607 | }
1608 | },
1609 | "autoload": {
1610 | "classmap": [
1611 | "src/"
1612 | ]
1613 | },
1614 | "notification-url": "https://packagist.org/downloads/",
1615 | "license": [
1616 | "BSD-3-Clause"
1617 | ],
1618 | "authors": [
1619 | {
1620 | "name": "Sebastian Bergmann",
1621 | "email": "sebastian@phpunit.de",
1622 | "role": "lead"
1623 | }
1624 | ],
1625 | "description": "Collection of value objects that represent the types of the PHP type system",
1626 | "homepage": "https://github.com/sebastianbergmann/type",
1627 | "support": {
1628 | "issues": "https://github.com/sebastianbergmann/type/issues",
1629 | "source": "https://github.com/sebastianbergmann/type/tree/3.2.1"
1630 | },
1631 | "funding": [
1632 | {
1633 | "url": "https://github.com/sebastianbergmann",
1634 | "type": "github"
1635 | }
1636 | ],
1637 | "time": "2023-02-03T06:13:03+00:00"
1638 | },
1639 | {
1640 | "name": "sebastian/version",
1641 | "version": "3.0.2",
1642 | "source": {
1643 | "type": "git",
1644 | "url": "https://github.com/sebastianbergmann/version.git",
1645 | "reference": "c6c1022351a901512170118436c764e473f6de8c"
1646 | },
1647 | "dist": {
1648 | "type": "zip",
1649 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
1650 | "reference": "c6c1022351a901512170118436c764e473f6de8c",
1651 | "shasum": ""
1652 | },
1653 | "require": {
1654 | "php": ">=7.3"
1655 | },
1656 | "type": "library",
1657 | "extra": {
1658 | "branch-alias": {
1659 | "dev-master": "3.0-dev"
1660 | }
1661 | },
1662 | "autoload": {
1663 | "classmap": [
1664 | "src/"
1665 | ]
1666 | },
1667 | "notification-url": "https://packagist.org/downloads/",
1668 | "license": [
1669 | "BSD-3-Clause"
1670 | ],
1671 | "authors": [
1672 | {
1673 | "name": "Sebastian Bergmann",
1674 | "email": "sebastian@phpunit.de",
1675 | "role": "lead"
1676 | }
1677 | ],
1678 | "description": "Library that helps with managing the version number of Git-hosted PHP projects",
1679 | "homepage": "https://github.com/sebastianbergmann/version",
1680 | "support": {
1681 | "issues": "https://github.com/sebastianbergmann/version/issues",
1682 | "source": "https://github.com/sebastianbergmann/version/tree/3.0.2"
1683 | },
1684 | "funding": [
1685 | {
1686 | "url": "https://github.com/sebastianbergmann",
1687 | "type": "github"
1688 | }
1689 | ],
1690 | "time": "2020-09-28T06:39:44+00:00"
1691 | },
1692 | {
1693 | "name": "symplify/easy-coding-standard",
1694 | "version": "12.0.6",
1695 | "source": {
1696 | "type": "git",
1697 | "url": "https://github.com/easy-coding-standard/easy-coding-standard.git",
1698 | "reference": "7372622f5d9126ec50b0923d7eb6b778fac575a5"
1699 | },
1700 | "dist": {
1701 | "type": "zip",
1702 | "url": "https://api.github.com/repos/easy-coding-standard/easy-coding-standard/zipball/7372622f5d9126ec50b0923d7eb6b778fac575a5",
1703 | "reference": "7372622f5d9126ec50b0923d7eb6b778fac575a5",
1704 | "shasum": ""
1705 | },
1706 | "require": {
1707 | "php": ">=7.2"
1708 | },
1709 | "conflict": {
1710 | "friendsofphp/php-cs-fixer": "<3.0",
1711 | "squizlabs/php_codesniffer": "<3.6",
1712 | "symplify/coding-standard": "<11.3"
1713 | },
1714 | "bin": [
1715 | "bin/ecs"
1716 | ],
1717 | "type": "library",
1718 | "autoload": {
1719 | "files": [
1720 | "bootstrap.php"
1721 | ]
1722 | },
1723 | "notification-url": "https://packagist.org/downloads/",
1724 | "license": [
1725 | "MIT"
1726 | ],
1727 | "description": "Use Coding Standard with 0-knowledge of PHP-CS-Fixer and PHP_CodeSniffer",
1728 | "keywords": [
1729 | "Code style",
1730 | "automation",
1731 | "fixer",
1732 | "static analysis"
1733 | ],
1734 | "support": {
1735 | "issues": "https://github.com/easy-coding-standard/easy-coding-standard/issues",
1736 | "source": "https://github.com/easy-coding-standard/easy-coding-standard/tree/12.0.6"
1737 | },
1738 | "funding": [
1739 | {
1740 | "url": "https://www.paypal.me/rectorphp",
1741 | "type": "custom"
1742 | },
1743 | {
1744 | "url": "https://github.com/tomasvotruba",
1745 | "type": "github"
1746 | }
1747 | ],
1748 | "time": "2023-07-25T17:12:00+00:00"
1749 | },
1750 | {
1751 | "name": "theseer/tokenizer",
1752 | "version": "1.2.1",
1753 | "source": {
1754 | "type": "git",
1755 | "url": "https://github.com/theseer/tokenizer.git",
1756 | "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
1757 | },
1758 | "dist": {
1759 | "type": "zip",
1760 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
1761 | "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
1762 | "shasum": ""
1763 | },
1764 | "require": {
1765 | "ext-dom": "*",
1766 | "ext-tokenizer": "*",
1767 | "ext-xmlwriter": "*",
1768 | "php": "^7.2 || ^8.0"
1769 | },
1770 | "type": "library",
1771 | "autoload": {
1772 | "classmap": [
1773 | "src/"
1774 | ]
1775 | },
1776 | "notification-url": "https://packagist.org/downloads/",
1777 | "license": [
1778 | "BSD-3-Clause"
1779 | ],
1780 | "authors": [
1781 | {
1782 | "name": "Arne Blankerts",
1783 | "email": "arne@blankerts.de",
1784 | "role": "Developer"
1785 | }
1786 | ],
1787 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
1788 | "support": {
1789 | "issues": "https://github.com/theseer/tokenizer/issues",
1790 | "source": "https://github.com/theseer/tokenizer/tree/1.2.1"
1791 | },
1792 | "funding": [
1793 | {
1794 | "url": "https://github.com/theseer",
1795 | "type": "github"
1796 | }
1797 | ],
1798 | "time": "2021-07-28T10:34:58+00:00"
1799 | }
1800 | ],
1801 | "aliases": [],
1802 | "minimum-stability": "stable",
1803 | "stability-flags": [],
1804 | "prefer-stable": false,
1805 | "prefer-lowest": false,
1806 | "platform": {
1807 | "php": ">=7.4"
1808 | },
1809 | "platform-dev": [],
1810 | "plugin-api-version": "2.0.0"
1811 | }
1812 |
--------------------------------------------------------------------------------
/doc/QAP1_protocol.txt:
--------------------------------------------------------------------------------
1 | QAP1 Protocol
2 | ==============================
3 |
4 | Any interested developers are welcome to improve Rserve since it is released under GPL. You can download the sources from the download section. As you can easily see from the directory structure I hold the sources in a CVS repository, therefore anyone who wants to contribute to the development should send me an e-mail (Simon.Urbanek@r-project.org) in order to obtain access to the CVS.
5 |
6 | Technical Documentation for Rserve
7 | ----------------------------------
8 | This document describes the protocols and structures used by Rserve (version 0.1-9). This information is helpful for implementing Rserve clients.
9 | Rserve communication is performed over any reliable connection-oriented protocol (usually TCP/IP; Rserve 0.1-9 supports TCP/IP and local unix sockets). After connection is established, the server sends 32 bytes representing the ID-string defining the capabilities of the server. Each attribute of the ID-string is 4 bytes long and is meant to be user- readable (i.e. use no special characters), and it's a good idea to make "\r\n\r\n" the last attribute.
10 |
11 | the ID string must be of the form:
12 |
13 | [0] "Rsrv" - R-server ID signature
14 | [4] "0100" - version of the R server protocol
15 | [8] "QAP1" - protocol used for communication (here Quad Attributes Packets v1)
16 | [12] any additional attributes follow. \r\n and '-' are ignored.
17 | optional attributes (in any order; it is legitimate to put dummy attributes, like "----" or " " between attributes):
18 | "R151" - version of R (here 1.5.1)
19 | "ARpt" - authorization required (here "pt"=plain text, "uc"=unix crypt)
20 | connection will be closed
21 | if the first packet is not CMD_login.
22 | if more AR.. methods are specified, then client is free to
23 | use the one he supports (usually the most secure)
24 | "K***" - key if encoded authentification is challenged (*** is the key)
25 | for unix crypt the first two letters of the key are the salt
26 | required by the server */
27 | The protocol specified in the third attribute (here QAP1) is used immediately after the ID string was transmitted.
28 |
29 | QAP1 message oriented protocol
30 | -----------------------------
31 |
32 | QAP1 (quad attributes protocol v1) is a message oriented protocol, i.e. the initiating side (here the client) sends a message and awaits a response. The message contains both the action to be taken and any necessary data. The response contains a response code and any associated data. Every message consists of a header and data part (which can be empty). The header is structured as follows:
33 |
34 | [0] (int) command
35 | [4] (int) length of the message (bits 0-31)
36 | [8] (int) offset of the data part
37 | [12] (int) length of the message (bits 32-63)
38 | command specifies the request or response type.
39 | length specifies the number of bytes belonging to this message (excluding the header).
40 | offset specifies the offset of the data part, where 0 means directly after the header (which is normally the case)
41 | length2 high bits of the length (must be 0 if the packet size is smaller than 4GB)
42 | The header must always be transmitted en-block. Data part can be split into packets of an arbitrary size. Each message consists of 16 bytes (the header) plus data. Therefore a message consists of length+16 bytes (where length is the size of the data payload).
43 |
44 | The data part contains any additional parameters that are send along with the command. Each parameter consists of a 4-byte header:
45 |
46 | [0] (byte) type
47 | [1] (24-bit int) length
48 | Types used by the current Rserve implementation (for list of all supported types see Rsrv.h):
49 | * DT_INT (4 bytes) integer
50 | * DT_STRING (n bytes) null terminated string
51 | * DT_BYTESTREAM (n bytes) any binary data
52 | * DT_SEXP R's encoded SEXP, see below
53 | all int and double entries throughout the transfer are encoded in Intel-endianess format:
54 | int=0x12345678 -> char[4]=(0x78,0x56,x34,0x12) functions/macros for converting from native to protocol format are available in Rsrv.h.
55 | Commands supported by Rserve
56 |
57 | Supported commands:
58 |
59 | command parameters | response data
60 |
61 | CMD_login DT_STRING | -
62 | CMD_voidEval DT_STRING | -
63 | CMD_eval DT_STRING | DT_SEXP
64 | CMD_shutdown [DT_STRING] | -
65 | CMD_openFile DT_STRING | -
66 | CMD_createFile DT_STRING | -
67 | CMD_closeFile - | -
68 | CMD_readFile [DT_INT] | DT_BYTESTREAM
69 | CMD_writeFile DT_BYTESTREAM | -
70 | CMD_removeFile DT_STRING | -
71 | CMD_setSEXP DT_STRING, | -
72 | DT_SEXP
73 | CMD_assignSEXP DT_STRING, | -
74 | DT_SEXP
75 | CMD_setBufferSize DT_INT | -
76 | CMD_setEncoding DT_STRING | - (since 0.5-3)
77 | CMD_ctrlEval DT_STRING | - (since 0.6-0)
78 | CMD_ctrlSource DT_STRING | - (since 0.6-0)
79 | CMD_ctrlShutdown - | - (since 0.6-0)
80 |
81 | (Parameters in brackets [] are optional)
82 |
83 | Responses:
84 | The CMD_RESP mask is set for all responses. Each response consists of the response command (RESP_OK or RESP_ERR - least significant 24 bit) and the status code (most significant 8 bits). For a list of all currently supported status codes see ERR_... in Rsrv.h.
85 |
86 | Note: Commands with four highest bits set (0xf0) are reserved as internal/special and their data payload does not follow the regular pattern. They should not be used by clients.
87 |
88 | Encoding of SEXP R expression
89 | ------------------------------
90 |
91 | R SEXP value (DT_SEXP) are recursively encoded in a similar way as the parameter attributes. Each SEXP consists of a 4-byte header and the actual contents. The header is of the form:
92 |
93 | [0] (byte) eXpression Type
94 | [1] (24-bit int) length
95 | The expression type consists of the actual type (least significant 6 bits) and attributes. Follwing expression types are supported:
96 | XT_NULL data: -
97 | - XT_INT data: (4) int
98 | - XT_DOUBLE data: (8) double
99 | - XT_STR data: (n) char null-term. strg.
100 | - XT_LANG data: same as XT_LIST
101 | - XT_SYM data: (n) char symbol name
102 | - XT_BOOL data: (1) byte boolean
103 | (1=TRUE, 0=FALSE, 2=NA)
104 | + XT_S4 data: -
105 |
106 | XT_VECTOR data: (n*?) SEXP
107 | - XT_LIST data: SEXP head, SEXP vals, [SEXP tag]
108 | XT_CLOS data: SEXP formals, SEXP body
109 | + XT_SYMNAME data: same as XT_STR
110 | + XT_LIST_NOTAG data: same as XT_VECTOR
111 | + XT_LIST_TAG data: SEXP tag, SEXP value, ...
112 | + XT_LANG_NOTAG data: same as XT_LIST_NOTAG (LANGSXP)
113 | + XT_LANG_TAG data: same as XT_LIST_TAG (LANGSXP)
114 | + XT_VECTOR_EXP data: same as XT_VECTOR (EXPSXP)
115 |
116 | XT_ARRAY_INT data: (n*4) int,int,..
117 | XT_ARRAY_DOUBLE data: (n*8) double,double,..
118 | XT_ARRAY_STR data: (?) string,string,..
119 | XT_ARRAY_BOOL data: (n) byte,byte,..
120 | + XT_RAW data: (1) int n (n) byte,byte,..
121 | + XT_ARRAY_CPLX data: (n) double(re),double(im),..
122 |
123 | XT_UNKNOWN data: (4) int - SEXP type as defined in R
124 |
125 | - = removed in protocol 0103 (Rserve 0.5)
126 | + = new since protocol 0103 (Rserve 0.5)
127 | Attributes:
128 | XT_HAS_ATTR - if this flag is set then the SEXP has an attribute list which is stored before the actual expression. In this case the layout looks as follows:
129 | [0] (4) header SEXP: len=4+m+n, XT_HAS_ATTR is set
130 | [4] (4) header attribute SEXP: len=n
131 | [8] (n) data attribute SEXP
132 | [8+n] (m) data SEXP
133 |
--------------------------------------------------------------------------------
/doc/QAP_message.txt:
--------------------------------------------------------------------------------
1 |
2 | +---------------------------------------------------------------+
3 | | Header (16 bits) |
4 | | + 4 bytes + 4 bytes + 4 bytes + 4 bytes + |
5 | | +------------+------------+-----------+-----------+ |
6 | | | Command | length-low | offset | length-hi | |
7 | | +------------+------------+-----------+-----------+ |
8 | +---------------------------------------------------------------+
9 | | Data Part |
10 | | +-------------------------------------------------------+ |
11 | | | Header (4 bytes) | |
12 | | | Type (1 byte) : DT_* Length (3 bytes) | |
13 | | +-------------------------------------------------------+ |
14 | | + Data (length bytes) | |
15 | | +-------------------------------------------------------+ |
16 | | +-------------------------------------------------------+ |
17 | | | Header (4 bytes) | |
18 | | | Type (1 byte) : DT_* Length (3 bytes) | |
19 | | +-------------------------------------------------------+ |
20 | | + Data (length bytes) | |
21 | | +-------------------------------------------------------+ |
22 |
--------------------------------------------------------------------------------
/doc/original_version_simple.php:
--------------------------------------------------------------------------------
1 | >= 8; $r .= chr($i & 255); $i >>=8; $r .= chr($i & 255); $i >>=8; $r .= chr($i & 255); return $r; }
42 | function _rserve_mkint24($i) { $r = chr($i & 255); $i >>= 8; $r .= chr($i & 255); $i >>=8; $r .= chr($i & 255); return $r; }
43 | function _rserve_flt64($buf, $o=0) { $ss = substr($buf, $o, 8); if ($machine_is_bigendian) for ($k = 0; $k < 7; $k++) $ss[7 - $k] = $buf[$o + $k]; $r = unpack("d", substr($buf, $o, 8)); return $r[1]; }
44 |
45 | function mkp_str($cmd, $string) {
46 | $n = strlen($string) + 1; $string .= chr(0);
47 | while (($n & 3) != 0) { $string .= chr(1); $n++; }
48 | return _rserve_mkint32($cmd) . _rserve_mkint32($n + 4) . _rserve_mkint32(0) . _rserve_mkint32(0) . chr(4) . _rserve_mkint24($n) . $string;
49 | }
50 |
51 | function get_rsp($socket) {
52 | $n = socket_recv($socket, $buf, 16, 0);
53 | if ($n != 16) return FALSE;
54 | $len = _rserve_int32($buf, 4);
55 | $ltg = $len;
56 | while ($ltg > 0) {
57 | $n = socket_recv($socket, $b2, $ltg, 0);
58 | if ($n > 0) { $buf .= $b2; unset($b2); $ltg -= $n; } else break;
59 | }
60 | return $buf;
61 | }
62 |
63 | // parse SEXP results -- limited implementation for now (large packets and some data types are not supported)
64 | function parse_SEXP($buf, $offset, $attr = NULL) {
65 | $r = $buf;
66 | $i = $offset;
67 | // some simple parsing - just skip attributes and assume short responses
68 | $ra = _rserve_int8($r, $i);
69 | $rl = _rserve_int24($r, $i + 1);
70 | $i += 4;
71 | $offset = $eoa = $i + $rl;
72 | // echo "[data type ".($ra & 63).", length ".$rl." with payload from ".$i." to ".$eoa."]
\n";
73 | if (($ra & 64) == 64) {
74 | echo "sorry, long packets are not supported (yet)."; return FALSE;
75 | }
76 | if ($ra > 127) {
77 | $ra &= 127;
78 | $al = _rserve_int24($r, $i + 1);
79 | $attr = parse_SEXP($buf, $i);
80 | $i += $al + 4;
81 | }
82 | if ($ra == 0) return NULL;
83 | if ($ra == 16) { // generic vector
84 | $a = array();
85 | while ($i < $eoa)
86 | $a[] = parse_SEXP($buf, &$i);
87 | // if the 'names' attribute is set, convert the plain array into a map
88 | if (isset($attr['names'])) {
89 | $names = $attr['names']; $na = array(); $n = count($a);
90 | for ($k = 0; $k < $n; $k++) $na[$names[$k]] = $a[$k];
91 | return $na;
92 | }
93 | return $a;
94 | }
95 | if ($ra == 19) { // symbol
96 | $oi = $i; while ($i < $eoa && ord($r[$i]) != 0) $i++;
97 | return substr($buf, $oi, $i - $oi);
98 | }
99 | if ($ra == 20 || $ra == 22) { // pairlist w/o tags
100 | $a = array();
101 | while ($i < $eoa) $a[] = parse_SEXP($buf, &$i);
102 | return $a;
103 | }
104 | if ($ra == 21 || $ra == 23) { // pairlist with tags
105 | $a = array();
106 | while ($i < $eoa) { $val = parse_SEXP($buf, &$i); $tag = parse_SEXP($buf, &$i); $a[$tag] = $val; }
107 | return $a;
108 | }
109 | if ($ra == 32) { // integer array
110 | $a = array();
111 | while ($i < $eoa) { $a[] = _rserve_int32($r, $i); $i += 4; }
112 | if (count($a) == 1) return $a[0];
113 | return $a;
114 | }
115 | if ($ra == 33) { // double array
116 | $a = array();
117 | while ($i < $eoa) { $a[] = _rserve_flt64($r, $i); $i += 8; }
118 | if (count($a) == 1) return $a[0];
119 | return $a;
120 | }
121 | if ($ra == 34) { // string array
122 | $a = array();
123 | $oi = $i;
124 | while ($i < $eoa) {
125 | if (ord($r[$i]) == 0) {
126 | $a[] = substr($r, $oi, $i - $oi);
127 | $oi = $i + 1;
128 | }
129 | $i++;
130 | }
131 | if (count($a) == 1) return $a[0];
132 | return $a;
133 | }
134 | if ($ra == 36) { // boolean vector
135 | $n = _rserve_int32($r, $i); $i += 4; $k = 0;
136 | $a = array();
137 | while ($k < $n) { $v = _rserve_int8($r, $i++); $a[$k++] = ($v == 1) ? TRUE : (($v == 0) ? FALSE : NULL); }
138 | if ($n == 1) return $a[0];
139 | return $a;
140 | }
141 | if ($ra == 37) { // raw vector
142 | $len = _rserve_int32($r, $i); $i += 4;
143 | return substr($r, $i, $len);
144 | }
145 | if ($ra == 48) { // unimplemented type in Rserve
146 | $uit = _rserve_int32($r, $i);
147 | // echo "Note: result contains type #$uit unsupported by Rserve.
";
148 | return NULL;
149 | }
150 | echo "Warning: type ".$ra." is currently not implemented in the PHP client.";
151 | return FALSE;
152 | }
153 |
154 | //------------ Rserve API functions
155 |
156 | // if port is 0 then host is interpreted as unix socket, otherwise host is the host to connect to (default is local) and port is the TCP port number (6311 is the default)
157 | function Rserve_connect($host="127.0.0.1", $port=6311) {
158 | if ($port == 0)
159 | $ok = (($socket = socket_create(AF_UNIX, SOCK_STREAM, 0)) and (socket_connect($socket, $host)));
160 | else
161 | $ok = (($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) and (socket_connect($socket, $host, $port)));
162 | if ($ok) {
163 | $n = socket_recv($socket, $buf, 32, 0);
164 | if ($n < 32 || strncmp($buf, "Rsrv", 4) != 0) {
165 | echo "Invalid response from server.";
166 | return FALSE;
167 | }
168 | $rv = substr($buf, 4, 4);
169 | if (strcmp($rv, "0103") != 0) {
170 | echo "Unsupported protocol version.";
171 | return FALSE;
172 | }
173 | } else {
174 | echo "Unable to connect
".socket_strerror(socket_last_error()).""; 175 | return FALSE; 176 | } 177 | return $socket; 178 | } 179 | 180 | function Rserve_eval($socket, $command, $attr = NULL) { 181 | $pkt = mkp_str(3, $command); 182 | socket_send($socket, $pkt, strlen($pkt), 0); 183 | $r = get_rsp($socket); 184 | $res = _rserve_int32($r); 185 | $sc = ($res >> 24) & 127; 186 | $rr = $res & 255; 187 | if ($rr != 1) { echo "eval failed with error code " . $sc; return FALSE; } 188 | if (_rserve_int8($r, 16) != 10) { echo "invalid response (expecting SEXP)"; return FALSE; } 189 | $i = 20; 190 | return parse_SEXP($r, $i, &$attr); 191 | } 192 | 193 | function Rserve_close($socket) { 194 | return socket_close($socket); 195 | } 196 | 197 | //========== FastRWeb - compatible requests - sample use of the client to behave like Rcgi in FastRWeb 198 | 199 | $root = "/var/FastRWeb"; // set to the root of your FastRWeb installation - must be absolute 200 | 201 | function process_FastRWeb() { 202 | global $root; 203 | // $req = array_merge($_GET, $_POST); 204 | $path = $_SERVER['PATH_INFO']; 205 | if (!isset($path)) { echo "No path specified."; return FALSE; } 206 | $sp = str_replace("..", "_", $path); // sanitize paths 207 | $script = "$root/web.R$sp.R"; 208 | if (!file_exists($script)) { echo "Script [$script] $sp.R does not exist."; return FALSE; } 209 | // escape dangerous characters 210 | $script = str_replace("\\", "\\\\", $script); 211 | $script = str_replace("\"", "\\\"", $script); 212 | $qs = str_replace("\\", "\\\\", $_SERVER['QUERY_STRING']); 213 | $qs = str_replace("\"", "\\\"", $qs); 214 | $s = Rserve_connect(); 215 | $r = Rserve_eval($s, "{ qs<-\"$qs\"; setwd('$root/tmp'); library(FastRWeb); .out<-''; cmd<-'html'; ct<-'text/html'; hdr<-''; pars<-list(); lapply(strsplit(strsplit(qs,\"&\")[[1]],\"=\"),function(x) pars[[x[1]]]<<-x[2]); if(exists('init') && is.function(init)) init(); as.character(try({source(\"$script\"); as.WebResult(do.call(run, pars)) },silent=TRUE))}"); 216 | Rserve_close($s); 217 | 218 | if (!is_array($r)) { // this ususally means that an erro rocurred since the returned value is jsut a string 219 | ob_end_flush(); 220 | echo $r; 221 | exit(0); 222 | } 223 | 224 | if (isset($r[2])) header("Content-type: $r[2]"); 225 | 226 | if (($r[0] == "file") or ($r[0] == "tmpfile")) { 227 | $f = fopen($r[1], "rb"); 228 | $contents = ''; 229 | while (!feof($f)) $contents .= fread($f, 8192); 230 | fclose($f); 231 | ob_end_clean(); 232 | echo $contents; 233 | if ($r[0] == "tmpfile") unlink($r[0]); 234 | exit(0); 235 | } 236 | 237 | if ($r[0] == "html") { 238 | ob_end_clean(); 239 | echo (is_array($r[1]) ? implode("\n", $r[1]) : $r[1]); 240 | exit(0); 241 | } 242 | 243 | print_r($r); 244 | 245 | ob_end_flush(); 246 | 247 | exit(0); 248 | } 249 | 250 | //--- uncomment the following line if you want this script to serve as FastRWeb handler (see FastRWeb package and IASC paper) 251 | // process_FastRWeb(); 252 | 253 | //========== user code -- example and test -- 254 | 255 | $s = Rserve_connect(); 256 | if ($s == FALSE) { 257 | echo "Connect FAILED"; 258 | } else { 259 | print_r (Rserve_eval($s, "list(str=R.version.string,foo=1:10,bar=1:5/2,logic=c(TRUE,FALSE,NA))")); 260 | echo ""; 261 | print_r (Rserve_eval($s, "{x=rnorm(10); y=x+rnorm(10)/2; lm(y~x)}")); 262 | 263 | Rserve_close($s); 264 | } 265 | 266 | ob_end_flush(); 267 | 268 | ?> 269 | -------------------------------------------------------------------------------- /example/config.php: -------------------------------------------------------------------------------- 1 | evalString($command); 28 | //var_dump($r); 29 | } catch(Rserve_Exception $e) { 30 | var_dump($e); 31 | } 32 | 33 | echo "NativeArray\n"; 34 | $parser = new NativeArray(array('wrapper'=>true)); 35 | try { 36 | $command = 'seq(1,10, by=NA)'; 37 | $command = 'r= try({'.$command.'}, silent=T); if( inherits(r,"try-error")) { r = structure(list(message=unclass(r)), class="try-error") }; r'; 38 | $r = $cnx->evalString($command, $parser); 39 | 40 | var_dump($r); 41 | } catch(Rserve_Exception $e) { 42 | var_dump($e); 43 | } 44 | 45 | echo "REXP\n"; 46 | $parser = new REXP(); 47 | try { 48 | $command = 'seq(1,10, by=NA)'; 49 | $command = 'try({'.$command.'}, silent=T)'; 50 | $r = $cnx->evalString($command, $parser); 51 | 52 | $class = $r->getAttribute('class'); 53 | if($class) { 54 | $class = $class->getValues(); 55 | } 56 | 57 | //var_dump($class); 58 | 59 | //var_dump($r); 60 | } catch(Rserve_Exception $e) { 61 | var_dump($e); 62 | } 63 | 64 | -------------------------------------------------------------------------------- /example/evaluator.php: -------------------------------------------------------------------------------- 1 | evaluate('seq(1,10, by=NA)'); 22 | var_dump($r); 23 | // Should have an class attribute set to "try-error" 24 | 25 | 26 | // Create evaluator with REXP parser 27 | $eval = new Evaluator($cnx, Evaluator::PARSER_REXP); 28 | $r = $eval->evaluate('seq(1,10, by=NA)'); 29 | var_dump($r); 30 | // Return an Error instance -------------------------------------------------------------------------------- /example/example1.php: -------------------------------------------------------------------------------- 1 | evalString('chisq.test(c(12,223,22,10))'); 20 | 21 | 22 | var_dump($r); 23 | 24 | // Do the same ChiSQ but using ArrayWrapper to get attributes with result 25 | $parser = new NativeArray(array('wrapper'=>true)); 26 | $r = $cnx->evalString('chisq.test(c(12,223,22,10))', $parser); 27 | 28 | var_dump($r); 29 | 30 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 |