Fwd: [PECL-CVS] cvs: pecl /cvsclient config.m4 cvsclient.c package.xml php_cvsclient.h
Jan Schneider <[email protected]>
| Newsgroups | gmane.comp.horde.chora |
|---|---|
| Message-ID | <[email protected]> |
This might become an interesting extension. ----- Weitergeleitete Nachricht von [email protected] ----- Datum: Sun, 30 Nov 2003 01:53:38 -0000 Von: Sara Golemon <[email protected]> Antwort an: Sara Golemon <[email protected]> Betreff: [PECL-CVS] cvs: pecl /cvsclient config.m4 cvsclient.c package.xml php_cvsclient.h An: [email protected] 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 -- PECL CVS Mailing List To unsubscribe, visit: http://www.php.net/unsub.php -- Chora mailing list Frequently Asked Questions: http://horde.org/faq/ To unsubscribe, mail: [email protected]
pollita-20031129205338.txt
(text/plain, 15 KB)
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 | | [email protected] so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Sara Golemon <[email protected]> | +----------------------------------------------------------------------+ */ #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>[email protected]</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 | | [email protected] so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Sara Golemon <[email protected]> | +----------------------------------------------------------------------+ */ #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 */