[chora] Fwd: [PECL-CVS] cvs: pecl /cvsclient config.m4 cvsclient.c
package.xml php_cvsclient.h
Jan Schneider
jan at horde.org
Sun Nov 30 09:54:34 PST 2003
This might become an interesting extension.
----- Weitergeleitete Nachricht von pollita at php.net -----
Datum: Sun, 30 Nov 2003 01:53:38 -0000
Von: Sara Golemon <pollita at php.net>
Antwort an: Sara Golemon <pollita at php.net>
Betreff: [PECL-CVS] cvs: pecl /cvsclient config.m4 cvsclient.c package.xml
php_cvsclient.h
An: pecl-cvs at lists.php.net
pollita Sat Nov 29 20:53:38 2003 EDT
Added files:
/pecl/cvsclient config.m4 cvsclient.c package.xml php_cvsclient.h
Log:
Initial Release
----- Ende der weitergeleiteten Nachricht -----
Jan.
--
http://www.horde.org - The Horde Project
http://www.ammma.de - discover your knowledge
http://www.tip4all.de - Deine private Tippgemeinschaft
-------------- next part --------------
Index: pecl/cvsclient/config.m4
+++ pecl/cvsclient/config.m4
PHP_ARG_ENABLE(cvsclient, whether to enable the CVS client stream wrapper,
[ --enable-cvsclient Enable PHP cvs:// wrapper.])
if test "$PHP_CVSCLIENT" != "no"; then
AC_DEFINE(WITH_CVSCLIENT, 1, [Whether you want the CVS client])
PHP_NEW_EXTENSION(cvsclient, cvsclient.c,
$ext_shared,,)
fi
Index: pecl/cvsclient/cvsclient.c
+++ pecl/cvsclient/cvsclient.c
/*
+----------------------------------------------------------------------+
| PHP Version 4 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2002 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 2.02 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available at through the world-wide-web at |
| http://www.php.net/license/2_02.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license at php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Sara Golemon <pollita at php.net> |
+----------------------------------------------------------------------+
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#if WITH_CVSCLIENT
#include "php_cvsclient.h"
#include "php_globals.h"
#include "php_network.h"
#include "ext/standard/url.h"
#include "ext/standard/info.h"
#include <sys/socket.h>
#include <ctype.h>
#define PHP_CVSCLIENT_REQ_ARGUMENT 0x00000001
#define PHP_CVSCLIENT_REQ_ARGUMENTX 0x00000002
#define PHP_CVSCLIENT_REQ_DIRECTORY 0x00000004
#define PHP_CVSCLIENT_REQ_ROOT 0x00000008
#define PHP_CVSCLIENT_REQ_REPOSITORY 0x00000010
#define PHP_CVSCLIENT_REQ_UPDATE 0x00000020
#define PHP_CVSCLIENT_REQ_CI 0x00000040
#define PHP_CVSCLIENT_REQ_CO 0x00000080
#define PHP_CVSCLIENT_REQ_DIFF 0x00000100
#define PHP_CVSCLIENT_REQ_LOG 0x00000200
#define PHP_CVSCLIENT_REQ_ADD 0x00000400
#define PHP_CVSCLIENT_REQ_REMOVE 0x00000800
#define PHP_CVSCLIENT_REQ_HISTORY 0x00001000
typedef struct _php_cvsclient_requests {
long request;
char *label;
} php_cvsclient_requests;
static php_cvsclient_requests cvsclient_requests[] = {
{ PHP_CVSCLIENT_REQ_ARGUMENT, "argument" },
{ PHP_CVSCLIENT_REQ_ARGUMENTX, "argumentx" },
{ PHP_CVSCLIENT_REQ_DIRECTORY, "directory" },
{ PHP_CVSCLIENT_REQ_ROOT, "root" },
{ PHP_CVSCLIENT_REQ_REPOSITORY, "repository" },
{ PHP_CVSCLIENT_REQ_UPDATE, "update" },
{ PHP_CVSCLIENT_REQ_CI, "ci" },
{ PHP_CVSCLIENT_REQ_CO, "co" },
{ PHP_CVSCLIENT_REQ_DIFF, "diff" },
{ PHP_CVSCLIENT_REQ_LOG, "log" },
{ PHP_CVSCLIENT_REQ_ADD, "add" },
{ PHP_CVSCLIENT_REQ_REMOVE, "remove" },
{ PHP_CVSCLIENT_REQ_HISTORY, "history" },
{ 0, NULL }
};
static char cvs_encode[96] =
{ 32, 120, 53, 35, 36, 109, 72, 108,
70, 64, 76, 67, 116, 74, 68, 87,
111, 52, 75, 119, 49, 34, 82, 81,
95, 65, 112, 86, 118, 110, 122, 105,
64, 57, 83, 43, 46, 102, 40, 89,
38, 103, 45, 50, 42, 123, 91, 35,
125, 55, 54, 66, 124, 126, 59, 47,
92, 71, 115, 91, 92, 93, 94, 56,
96, 121, 117, 104, 101, 100, 69, 73,
99, 63, 94, 93, 39, 37, 61, 48,
58, 113, 32, 90, 44, 98, 60, 51,
33, 97, 62, 123, 124, 125, 126, 127 };
function_entry cvsclient_functions[] = {
/* TODO: Resource based single-session access and committment */
{NULL, NULL, NULL}
};
zend_module_entry cvsclient_module_entry = {
STANDARD_MODULE_HEADER,
"cvsclient",
cvsclient_functions,
PHP_MINIT(cvsclient),
PHP_MSHUTDOWN(cvsclient),
NULL, /* RINIT */
NULL, /* RSHUTDOWN */
PHP_MINFO(cvsclient),
NO_VERSION_YET,
STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_CVSCLIENT
ZEND_GET_MODULE(cvsclient)
#endif
/* {{{ php_cvsclient_do_connect */
static php_stream * php_cvsclient_do_connect(char *path, int options, php_stream_context *context, php_url **presource STREAMS_DC TSRMLS_DC)
{
php_stream *stream = NULL;
php_url *resource = NULL;
resource = php_url_parse((char *) path);
if (!resource || !resource->scheme || !resource->host) {
goto connect_errexit;
}
if (strcasecmp("cvs", resource->scheme)) {
goto connect_errexit;
}
/* use port 2401 if one wasn't specified */
if (resource->port == 0) {
resource->port = 2401;
}
stream = php_stream_sock_open_host(resource->host, resource->port, SOCK_STREAM, NULL, 0);
if (stream == NULL) {
goto connect_errexit;
}
php_stream_context_set(stream, context);
php_stream_notify_info(context, PHP_STREAM_NOTIFY_CONNECT, NULL, 0);
if (presource) {
*presource = resource;
} else {
php_url_free(resource);
}
return stream;
connect_errexit:
if (resource) {
php_url_free(resource);
}
if (stream) {
php_stream_close(stream);
}
return NULL;
}
/* }}} */
/* {{{ php_cvsclient_encode
*/
static char * php_cvsclient_encode(const char *orig)
{
unsigned char *enc;
int i;
enc = estrdup(orig);
for(i=0; i<strlen(enc); i++) {
if (enc[i] >= 32 && enc[i] <= 127) {
enc[i] = cvs_encode[enc[i] - 32];
}
}
return enc;
}
/* }}} */
/* {{{ php_cvsclient_authenticate
*/
static int php_cvsclient_authenticate(php_stream *stream, const char *cvsroot, const char *user, const char *pass STREAMS_DC TSRMLS_DC)
{
char *encpw;
char response[128];
encpw = php_cvsclient_encode(pass);
php_stream_write_string(stream, "BEGIN AUTH REQUEST\n");
php_stream_printf(stream TSRMLS_CC, "%s\n", cvsroot);
php_stream_printf(stream TSRMLS_CC, "%s\n", user);
php_stream_printf(stream TSRMLS_CC, "A%s\n", encpw);
php_stream_write_string(stream, "END AUTH REQUEST\n");
efree(encpw);
/* Who do you love? */
if (php_stream_gets(stream, response, sizeof(response)-1) == NULL) {
return FAILURE;
}
if (strncmp(response, "I LOVE YOU", strlen("I LOVE YOU"))) {
return FAILURE;
}
return SUCCESS;
}
/* }}} */
/* {{{ php_cvsclient_negotiate */
static int php_cvsclient_negotiate(php_stream *stream, const char *cvsroot STREAMS_DC TSRMLS_DC)
{
php_cvsclient_requests *verbs = cvsclient_requests;
char response[4096];
int requests = 0, i;
php_stream_printf(stream TSRMLS_CC, "Root %s\n", cvsroot);
php_stream_printf(stream TSRMLS_CC, "Valid-responses %s %s %s\n",
"Valid-requests New-entry Updated Created Update-existing Merged Rcs-diff Patched Mode Mod-time Checksum",
"Copy-file Removed Remove-entry Set-static-directory Clear-static-directory Set-sticky Clear-sticky Template Set-checkin-prog",
"Set-update-prog Notified Module-expansion Wrapper-rcsOption ok error Checked-in M E F MT");
php_stream_write_string(stream, "valid-requests\n");
if (php_stream_gets(stream, response, sizeof(response)-1) == NULL) {
return 0;
}
for(i=0; i<strlen(response); i++) {
response[i] = tolower(response[i]);
}
/* TODO: Improve this, we could (and probably do) get false positives */
while (verbs->request && verbs->label) {
if (strstr(response, verbs->label)) {
requests |= verbs->request;
}
verbs++;
}
return requests;
}
/* }}} */
/* {{{ php_stream_url_wrap_cvsclient
*/
static php_stream * php_stream_url_wrap_cvsclient(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
{
php_cvsclient_requests *verbs = cvsclient_requests;
php_stream *stream, *memstream;
php_url *resource = NULL;
char *module = NULL;
char *cvsroot = NULL;
char *filepath = NULL;
char *filename, *p;
char response[4096];
int valid_requests, i;
long filesize;
zval *wrapperdata = NULL;
zval **tmpzval;
if (strpbrk(mode, "awx+")) {
php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "CVS wrapper does not support writeable connections (yet).");
return NULL;
}
/* Connect */
stream = php_cvsclient_do_connect(path, options, context, &resource STREAMS_CC TSRMLS_CC);
if (!stream || !resource->path) {
goto wrap_errexit;
}
p = strchr(resource->path + 1, '/');
if (p) {
cvsroot = estrndup(resource->path, p - resource->path);
filename = p;
p = strchr(filename + 1, '/');
if (p) {
module = estrndup(filename, p - filename);
filename = p;
p = strrchr(filename + 1, '/');
if (p) {
filepath = estrndup(filename, p - filename);
filename = p + 1;
} else {
filename++;
}
} else {
goto wrap_errexit;
}
} else {
goto wrap_errexit;
}
/* Authenticate */
if (resource && resource->user && resource->pass &&
php_cvsclient_authenticate(stream, cvsroot, resource->user, resource->pass STREAMS_CC TSRMLS_CC) == FAILURE) {
goto wrap_errexit;
}
/* Negotiate */
if ((valid_requests = php_cvsclient_negotiate(stream, cvsroot STREAMS_CC TSRMLS_CC)) == 0) {
goto wrap_errexit;
}
/* Request */
if (context &&
php_stream_context_get_option(context, "cvs", "revision", &tmpzval) == SUCCESS) {
SEPARATE_ZVAL(tmpzval);
convert_to_string_ex(tmpzval);
php_stream_printf(stream TSRMLS_CC, "Argument -r\nArgument %s\n", Z_STRVAL_PP(tmpzval));
}
php_stream_printf(stream TSRMLS_CC, "Argument %s\n", filename);
php_stream_write_string(stream, "Directory .\n");
php_stream_printf(stream TSRMLS_CC, "%s%s%s\n", cvsroot, module, filepath ? filepath : "");
php_stream_write_string(stream, "update\n");
efree(cvsroot);
cvsroot = NULL;
efree(module);
module = NULL;
if (filepath) {
efree(filepath);
filepath = NULL;
}
/* Parse response */
ALLOC_INIT_ZVAL(wrapperdata);
array_init(wrapperdata);
while (php_stream_gets(stream, response, sizeof(response)-1) != NULL) {
if (strncasecmp(response, "error", 5) == 0) {
goto wrap_errexit;
}
if (strncasecmp(response, "mod-time ", 9) == 0) {
add_assoc_string(wrapperdata, "mod-time", response + 9, 1);
}
if ((strlen(response) > strlen(filename) + 4) &&
response[0] == '/' &&
strncmp(response + 1, filename, strlen(filename)) == 0 &&
response[strlen(filename)+1] == '/') {
p = response + strlen(filename) + 2;
p = strchr(p, '/');
if (p) {
*p = '\0';
p = response + strlen(filename) + 2;
add_assoc_string(wrapperdata, "revision", p, 1);
}
}
/* TODO: Parse other elements into wrapperdata */
for(i=0; i<strlen(response); i++) {
if (!isdigit(response[i]) && !iscntrl(response[i])) {
goto header_loop;
}
}
break;
header_loop:
}
filesize = atoi(response);
add_assoc_long(wrapperdata, "filesize", filesize);
memstream = php_stream_fopen_tmpfile();
if (!memstream) {
goto wrap_errexit;
}
while (filesize) {
int read;
read = php_stream_read(stream, response, (filesize > (sizeof(response) - 1)) ? sizeof(response)-1 : filesize);
php_stream_write(memstream, response, read);
filesize -= read;
}
php_stream_rewind(memstream);
php_stream_close(stream);
memstream->wrapperdata = wrapperdata;
php_url_free(resource);
resource = NULL;
return memstream;
wrap_errexit:
if (filepath) {
efree(filepath);
}
if (module) {
efree(module);
}
if (cvsroot) {
efree(cvsroot);
}
if (wrapperdata) {
zval_ptr_dtor(&wrapperdata);
}
if (resource) {
php_url_free(resource);
}
if (stream) {
php_stream_close(stream);
}
return NULL;
}
/* }}} */
/* {{{ php_stream_cvsclient_stat
*/
static int php_stream_cvsclient_stat(php_stream_wrapper *wrapper,
php_stream *stream,
php_stream_statbuf *ssb
TSRMLS_DC)
{
/* For now, we return with a failure code to prevent the underlying
* file's details from being used instead. */
return -1;
}
/* }}} */
static php_stream_wrapper_ops cvsclient_stream_wops = {
php_stream_url_wrap_cvsclient,
NULL, /* stream_close */
php_stream_cvsclient_stat,
NULL, /* stat_url */
NULL, /* opendir */
"CVS"
#if PHP_MAJOR_VERSION >= 5
,NULL /* unlink */
#endif
};
PHPAPI php_stream_wrapper php_stream_cvsclient_wrapper = {
&cvsclient_stream_wops,
NULL,
1 /* is_url */
};
PHP_MINIT_FUNCTION(cvsclient)
{
/* TODO: Readonly support for cvs.log, cvs.history, etc... */
return php_register_url_stream_wrapper("cvs", &php_stream_cvsclient_wrapper TSRMLS_CC);
}
PHP_MSHUTDOWN_FUNCTION(cvsclient)
{
return php_unregister_url_stream_wrapper("cvs" TSRMLS_CC);
}
PHP_MINFO_FUNCTION(cvsclient)
{
php_info_print_table_start();
php_info_print_table_row(2, "CVS Client", "enabled");
php_info_print_table_row(2, "Wrapper", "cvs://");
php_info_print_table_end();
}
#endif
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/
Index: pecl/cvsclient/package.xml
+++ pecl/cvsclient/package.xml
<package version="1.0">
<name>cvsclient</name>
<summary>CVS pserver client</summary>
<description>
pserver client extension. Current version has read-only streams wrapper.
Later versions to include commit/diff/log support.
</description>
<license>PHP</license>
<maintainers>
<maintainer>
<user>pollita</user>
<name>Sara Golemon</name>
<email>pollita at php.net</email>
<role>lead</role>
</maintainer>
</maintainers>
<release>
<version>0.1</version>
<state>alpha</state>
<date>2003-11-29</date>
<notes>Initial Release</notes>
<filelist>
<file role="src" name="config.m4"/>
<file role="src" name="cvsclient.c"/>
<file role="src" name="php_cvsclient.h"/>
</filelist>
</release>
<deps>
<dep type="php" rel="ge">4.3.0</dep>
</deps>
</package>
Index: pecl/cvsclient/php_cvsclient.h
+++ pecl/cvsclient/php_cvsclient.h
/*
+----------------------------------------------------------------------+
| PHP Version 4 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2002 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 2.02 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available at through the world-wide-web at |
| http://www.php.net/license/2_02.txt. |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license at php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Sara Golemon <pollita at php.net> |
+----------------------------------------------------------------------+
*/
#ifndef PHP_CVSCLIENT_H
#define PHP_CVSCLIENT_H
#if WITH_CVSCLIENT
extern zend_module_entry cvsclient_module_entry;
#define phpext_cvsclient_ptr &cvsclient_module_entry
PHP_MINIT_FUNCTION(cvsclient);
PHP_MSHUTDOWN_FUNCTION(cvsclient);
PHP_MINFO_FUNCTION(cvsclient);
#else
#define phpext_cvsclient_ptr NULL
#endif /* WITH_CVSCLIENT */
#endif /* PHP_CVSCLIENT_H */
-------------- next part --------------
--
PECL CVS Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php
More information about the chora
mailing list