/* * Perforce Extension for PHP * * Copyright 2004 Jon Parise <jon@php.net>. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* $Header: //guest/tony_smith/perforce/API/php/perforce.cpp#4 $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" BEGIN_EXTERN_C() #include "ext/standard/info.h" END_EXTERN_C() #ifdef ZEND_ENGINE_2 #include "zend_object_handlers.h" #endif /* Avoid colliding with PHP's definition of HAVE_MMAP. */ #undef HAVE_MMAP /* Avoid colliding with winspool.h's definition of SetPort. */ #ifdef SetPort #undef SetPort #endif #include <clientapi.h> #include <strtable.h> #include "php_perforce.h" #include "p4result.h" #include "php_clientuser.h" #include "php_clientapi.h" /* {{{ Globals */ static zend_class_entry *perforce_class_entry_ptr; static int le_perforce = 0; /* }}} */ /* Helpers */ /* {{{ PHP_METHOD This is already defined by PHP5. Define it for PHP4. */ #ifndef PHP_METHOD #define PHP_METHOD(classname, name) \ ZEND_NAMED_FUNCTION(ZEND_FN(classname##_##name)) #endif /* }}} */ /* {{{ PHP_ME This is already defined by PHP5. Define it for PHP4. */ #ifndef PHP_ME #define PHP_ME(classname, name, arg_info, flags) \ ZEND_NAMED_FE(name, ZEND_FN(classname##_##name), arg_info) #endif /* }}} */ /* {{{ PHP_MALIAS This is already defined by PHP5. Define it for PHP4. */ #ifndef PHP_MALIAS #define PHP_MALIAS(classname, name, alias, arg_info, flags) \ ZEND_NAMED_FE(name, ZEND_FN(classname##_##alias), arg_info) #endif /* }}} */ /* {{{ PHP_PERFORCE_FETCH(p) */ #define PHP_PERFORCE_FETCH(p) \ { \ zval **tmp; \ if (zend_hash_find(Z_OBJPROP_P(this_ptr), "perforce", sizeof("perforce"), \ (void **)&tmp) != FAILURE) { \ p = (PhpClientApi *)zend_fetch_resource(tmp TSRMLS_CC, -1, \ "perforce", NULL, 1, \ le_perforce); \ } else { \ php_error(E_ERROR, "Failed to retrieve Perforce connection resource");\ p = NULL; \ } \ } /* }}} */ /* {{{ get_class_name(zval *object) */ static const char * get_class_name(zval *object TSRMLS_DC) { zend_class_entry *ce = NULL; #ifdef ZEND_ENGINE_2 char *class_name = NULL; zend_uint class_len; if ((Z_OBJ_HANDLER_P(object, get_class_name) && Z_OBJ_HANDLER_P(object, get_class_name)(object, &class_name, &class_len, 0 TSRMLS_CC) == SUCCESS)) { return class_name; } #endif ce = Z_OBJCE_P(object); return (ce) ? ce->name : NULL; } /* }}} */ /* {{{ perforce_destructor(void *object) */ static void perforce_destructor(void *object) { PhpClientApi *perforce = (PhpClientApi *)object; delete perforce; } /* }}} */ /* PerforceClient Methods */ /* {{{ proto void constructor(object ui) */ #ifdef ZEND_ENGINE_2 PHP_METHOD(PerforceClient, __construct) #else PHP_METHOD(PerforceClient, perforceclient) #endif { zval *ui; int ret; /* Initialize our new PerforceClient object. */ object_init_ex(this_ptr, perforce_class_entry_ptr); /* Create the Perforce Client object. */ PhpClientApi *perforce = new PhpClientApi(); /* Register the structure as a resource of this PerforceClient object. */ ret = zend_list_insert(perforce, le_perforce); add_property_resource(this_ptr, "perforce", ret); zend_list_addref(ret); } /* }}} */ /* {{{ proto bool debugLevel(int level) */ PHP_METHOD(PerforceClient, debugLevel) { PhpClientApi *perforce; int level; if (zend_parse_parameters(1 TSRMLS_CC, "l", &level) == FAILURE) { return; } PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; perforce->SetDebug( level ); RETURN_TRUE; } /* }}} */ /* {{{ proto bool setPort(string port) */ PHP_METHOD(PerforceClient, setPort) { PhpClientApi *perforce; char *port; int len; if (zend_parse_parameters(1 TSRMLS_CC, "s", &port, &len) == FAILURE) { return; } PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; perforce->SetPort(port); RETURN_TRUE; } /* }}} */ /* {{{ proto string getPort() */ PHP_METHOD(PerforceClient, getPort) { PhpClientApi *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr port(perforce->GetPort()); RETURN_STRINGL(port.Text(), port.Length(), 1); } /* }}} */ /* {{{ proto bool setUser(string user) */ PHP_METHOD(PerforceClient, setUser) { PhpClientApi *perforce; char *user; int len; if (zend_parse_parameters(1 TSRMLS_CC, "s", &user, &len) == FAILURE) { return; } PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; perforce->SetUser(user); RETURN_TRUE; } /* }}} */ /* {{{ proto string getUser() */ PHP_METHOD(PerforceClient, getUser) { PhpClientApi *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr user(perforce->GetUser()); RETURN_STRINGL(user.Text(), user.Length(), 1); } /* }}} */ /* {{{ proto bool setPassword(string password) */ PHP_METHOD(PerforceClient, setPassword) { PhpClientApi *perforce; char *password; int len; if (zend_parse_parameters(1 TSRMLS_CC, "s", &password, &len) == FAILURE) { return; } PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; perforce->SetPassword(password); RETURN_TRUE; } /* }}} */ /* {{{ proto string getPassword() */ PHP_METHOD(PerforceClient, getPassword) { PhpClientApi *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr password(perforce->GetPassword()); RETURN_STRINGL(password.Text(), password.Length(), 1); } /* }}} */ /* {{{ proto bool setClient(string client) */ PHP_METHOD(PerforceClient, setClient) { PhpClientApi *perforce; char *client; int len; if (zend_parse_parameters(1 TSRMLS_CC, "s", &client, &len) == FAILURE) { return; } PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; perforce->SetClient(client); RETURN_TRUE; } /* }}} */ /* {{{ proto string getClient() */ PHP_METHOD(PerforceClient, getClient) { PhpClientApi *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr client(perforce->GetClient()); RETURN_STRINGL(client.Text(), client.Length(), 1); } /* }}} */ /* {{{ proto bool tagged() */ PHP_METHOD(PerforceClient, tagged) { PhpClientApi *perforce; char *protocol, *value; int protocol_len, value_len; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; perforce->Tagged(); RETURN_TRUE; } /* }}} */ /* {{{ proto bool parseForms() */ PHP_METHOD(PerforceClient, parseForms) { PhpClientApi *perforce; char *protocol, *value; int protocol_len, value_len; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; perforce->ParseForms(); RETURN_TRUE; } /* }}} */ /* {{{ proto bool setCwd(string cwd) */ PHP_METHOD(PerforceClient, setCwd) { PhpClientApi *perforce; char *cwd; int len; if (zend_parse_parameters(1 TSRMLS_CC, "s", &cwd, &len) == FAILURE) { return; } PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; perforce->SetCwd(cwd); RETURN_TRUE; } /* }}} */ /* {{{ proto string getCwd() */ PHP_METHOD(PerforceClient, getCwd) { PhpClientApi *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr cwd(perforce->GetCwd()); RETURN_STRINGL(cwd.Text(), cwd.Length(), 1); } /* }}} */ /* {{{ proto bool setCharset(string charset) */ PHP_METHOD(PerforceClient, setCharset) { PhpClientApi *perforce; char *charset; int len; if (zend_parse_parameters(1 TSRMLS_CC, "s", &charset, &len) == FAILURE) { return; } PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; perforce->SetCharset(charset); RETURN_TRUE; } /* }}} */ /* {{{ proto string getCharset() */ PHP_METHOD(PerforceClient, getCharset) { PhpClientApi *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr charset(perforce->GetCharset()); RETURN_STRINGL(charset.Text(), charset.Length(), 1); } /* }}} */ /* {{{ proto bool setHost(string host) */ PHP_METHOD(PerforceClient, setHost) { PhpClientApi *perforce; char *host; int len; if (zend_parse_parameters(1 TSRMLS_CC, "s", &host, &len) == FAILURE) { return; } PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; perforce->SetHost(host); RETURN_TRUE; } /* }}} */ /* {{{ proto string getHost() */ PHP_METHOD(PerforceClient, getHost) { PhpClientApi *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr host(perforce->GetHost()); RETURN_STRINGL(host.Text(), host.Length(), 1); } /* }}} */ /* {{{ proto bool setLanguage(string language) */ PHP_METHOD(PerforceClient, setLanguage) { PhpClientApi *perforce; char *language; int len; if (zend_parse_parameters(1 TSRMLS_CC, "s", &language, &len) == FAILURE) { return; } PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; perforce->SetLanguage(language); RETURN_TRUE; } /* }}} */ /* {{{ proto string getLanguage() */ PHP_METHOD(PerforceClient, getLanguage) { PhpClientApi *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr language(perforce->GetLanguage()); RETURN_STRINGL(language.Text(), language.Length(), 1); } /* }}} */ /* {{{ proto string getOs() */ PHP_METHOD(PerforceClient, getOs) { PhpClientApi *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr os(perforce->GetOs()); RETURN_STRINGL(os.Text(), os.Length(), 1); } /* }}} */ /* {{{ proto bool init() Establish the connection. */ PHP_METHOD(PerforceClient, connect) { PhpClientApi *perforce = NULL; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; RETURN_BOOL( perforce->Connect() ); } /* }}} */ /* {{{ proto bool final() Close the connection and return true if there were no errors. */ PHP_METHOD(PerforceClient, disconnect) { PhpClientApi *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; RETURN_BOOL( perforce->Disconnect() ); } /* }}} */ /* {{{ proto bool dropped() Check if the connection is still open. */ PHP_METHOD(PerforceClient, dropped) { PhpClientApi *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; RETURN_BOOL( perforce->Dropped() ); } /* }}} */ /* {{{ proto bool setInput( string or hash ) Provide input for the following Perforce command. */ PHP_METHOD(PerforceClient, setInput) { PhpClientApi *perforce; zval ** args; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; // // we have to roll our own argument parsing here because we'll accept // either a string or an array as an argument // if( zend_get_parameters_array_ex( 1, &args ) == FAILURE ) { php_error( E_ERROR, "setInput() requires an argument" ); RETURN_FALSE; } switch( Z_TYPE_PP( args ) ) { case IS_STRING: case IS_ARRAY: perforce->SetInput( *args ); break; default: php_error( E_ERROR, "Argument to setInput must be hash or string" ); RETURN_FALSE; } RETURN_TRUE; } /* }}} */ /* {{{ proto bool run(string command) Run a Perforce command. */ PHP_METHOD(PerforceClient, run) { PhpClientApi *perforce; char *cmd = 0; int cmdlen = 0; zval **zargs = 0; zval **item = 0; zval *rval = 0; char **cargs = 0; int argc; int failed = 0; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; // // we have to roll our own argument parsing here because run takes a // variable argument list (min = 1) // argc = ZEND_NUM_ARGS(); if( !argc ) { php_error( E_ERROR, "Run() requires at least one argument" ); return; } if( zend_get_parameters_array_ex(ZEND_NUM_ARGS() , &zargs ) == FAILURE ) { php_error( E_ERROR, "Run(): error getting parameters" ); failed++; goto cleanup; } // // Allocate an array of char *'s to hold the C++ arguments for passing // down to Perforce // cargs = (char **) emalloc(sizeof(char *) * ( argc - 1 ) ); // // Iterate over the argument list converting from Zend format to C++ // format. The first argument is our command. // for( int i = 0; i < argc; i++ ) { item = zargs + i; // // Convert the argument to a string. If this is the first arg, then // it's the command so we split it off. The remaining args go into // the C-style array. // convert_to_string_ex( item ); if( i ) cargs[ i - 1 ] = Z_STRVAL_PP( item ); else cmd = Z_STRVAL_PP(item); } // // Due to the calling interface PHP uses, we have to duplicate // the result array here. Not nice, but the alternative (passing // a pointer to the return value all the way down to the P4Result class) // is worse. // rval = perforce->Run( cmd, argc - 1, cargs ); *return_value = *rval; zval_copy_ctor(return_value); cleanup: if( cargs ) efree( cargs ); if( !failed ) return; RETURN_FALSE; } /* }}} */ /* {{{ proto array output() Return an array of output from the last command. */ PHP_METHOD(PerforceClient, output) { PhpClientApi * perforce; zval * rval; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; rval = perforce->GetOutput(); *return_value = *rval; zval_copy_ctor(return_value); } /* }}} */ /* {{{ proto array warnings() Return an array of warnings from the last command. */ PHP_METHOD(PerforceClient, warnings) { PhpClientApi * perforce; zval * rval; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; rval = perforce->GetWarnings(); *return_value = *rval; zval_copy_ctor(return_value); } /* }}} */ /* {{{ proto array errors() Return an array of errors from the last command. */ PHP_METHOD(PerforceClient, errors) { PhpClientApi * perforce; zval * rval; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; rval = perforce->GetErrors(); *return_value = *rval; zval_copy_ctor(return_value); } /* }}} */ /* {{{ perforce_methods[] */ static function_entry perforce_methods[] = { #ifdef ZEND_ENGINE_2 PHP_ME(PerforceClient, __construct, NULL, 0) #else PHP_ME(PerforceClient, perforceclient, NULL, 0) #endif PHP_ME(PerforceClient, debugLevel, NULL, 0) PHP_ME(PerforceClient, errors, NULL, 0) PHP_ME(PerforceClient, setInput, NULL, 0) PHP_ME(PerforceClient, setPort, NULL, 0) PHP_ME(PerforceClient, getPort, NULL, 0) PHP_ME(PerforceClient, setUser, NULL, 0) PHP_ME(PerforceClient, getUser, NULL, 0) PHP_ME(PerforceClient, setPassword, NULL, 0) PHP_ME(PerforceClient, getPassword, NULL, 0) PHP_ME(PerforceClient, setClient, NULL, 0) PHP_ME(PerforceClient, getClient, NULL, 0) PHP_ME(PerforceClient, setCwd, NULL, 0) PHP_ME(PerforceClient, getCwd, NULL, 0) PHP_ME(PerforceClient, setCharset, NULL, 0) PHP_ME(PerforceClient, getCharset, NULL, 0) PHP_ME(PerforceClient, setHost, NULL, 0) PHP_ME(PerforceClient, getHost, NULL, 0) PHP_ME(PerforceClient, setLanguage, NULL, 0) PHP_ME(PerforceClient, getLanguage, NULL, 0) PHP_ME(PerforceClient, getOs, NULL, 0) PHP_ME(PerforceClient, connect, NULL, 0) PHP_ME(PerforceClient, disconnect, NULL, 0) PHP_ME(PerforceClient, dropped, NULL, 0) PHP_ME(PerforceClient, parseForms, NULL, 0) PHP_ME(PerforceClient, output, NULL, 0) PHP_ME(PerforceClient, run, NULL, 0) PHP_ME(PerforceClient, tagged, NULL, 0) PHP_ME(PerforceClient, warnings, NULL, 0) #ifndef ZEND_ENGINE_2 PHP_MALIAS(PerforceClient, debuglevel, debugLevel, NULL, 0) PHP_MALIAS(PerforceClient, setinput, setInput, NULL, 0) PHP_MALIAS(PerforceClient, setport, setPort, NULL, 0) PHP_MALIAS(PerforceClient, getport, getPort, NULL, 0) PHP_MALIAS(PerforceClient, setuser, setUser, NULL, 0) PHP_MALIAS(PerforceClient, getuser, getUser, NULL, 0) PHP_MALIAS(PerforceClient, setpassword, setPassword, NULL, 0) PHP_MALIAS(PerforceClient, getpassword, getPassword, NULL, 0) PHP_MALIAS(PerforceClient, setclient, setClient, NULL, 0) PHP_MALIAS(PerforceClient, getclient, getClient, NULL, 0) PHP_MALIAS(PerforceClient, setcwd, setCwd, NULL, 0) PHP_MALIAS(PerforceClient, getcwd, getCwd, NULL, 0) PHP_MALIAS(PerforceClient, setcharset, setCharset, NULL, 0) PHP_MALIAS(PerforceClient, getcharset, getCharset, NULL, 0) PHP_MALIAS(PerforceClient, sethost, setHost, NULL, 0) PHP_MALIAS(PerforceClient, gethost, getHost, NULL, 0) PHP_MALIAS(PerforceClient, setlanguage, setLanguage, NULL, 0) PHP_MALIAS(PerforceClient, getlanguage, getLanguage, NULL, 0) PHP_MALIAS(PerforceClient, getos, getOs, NULL, 0) PHP_MALIAS(PerforceClient, parseforms, parseForms, NULL, 0) #endif {NULL, NULL, NULL} }; /* }}} */ /* {{{ perforce_module_entry */ zend_module_entry perforce_module_entry = { STANDARD_MODULE_HEADER, "perforce", NULL, PHP_MINIT(perforce), PHP_MSHUTDOWN(perforce), NULL, NULL, PHP_MINFO(perforce), NO_VERSION_YET, STANDARD_MODULE_PROPERTIES }; #ifdef COMPILE_DL_PERFORCE BEGIN_EXTERN_C() ZEND_GET_MODULE(perforce) END_EXTERN_C() #endif /* }}} */ /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(perforce) { zend_class_entry ce; #ifdef ZEND_ENGINE_2 INIT_CLASS_ENTRY(ce, "PerforceClient", perforce_methods); #else INIT_CLASS_ENTRY(ce, "perforceclient", perforce_methods); #endif perforce_class_entry_ptr = zend_register_internal_class(&ce TSRMLS_CC); le_perforce = register_list_destructors(perforce_destructor, NULL); return SUCCESS; } /* }}} */ /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(perforce) { return SUCCESS; } /* }}} */ /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(perforce) { php_info_print_table_start(); php_info_print_table_row(2, "Perforce Support", "enabled"); php_info_print_table_end(); } /* }}} */ /* * Local variables: * c-basic-offset: 4 * tab-width: 4 * End: * vim600: fdm=marker * vim: sw=4 ts=4 noet */
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#4 | 4687 | Tony Smith |
Remove alias for non-existent function. Only caused a problem when you try and build with PHP4 |
||
#3 | 4686 | Tony Smith |
Minor bug fixes. Remove use of ZVAL_ZVAL which seems to be PHP5 specific. Also remove argument parsing to P4::Tagged() which is not necessary as there are no arguments. |
||
#2 | 4627 | Tony Smith |
Rework Jon Parise's PHP interface to work like P4Perl and P4Ruby, mostly. It's pretty close, but lacking method autoloading so the only way to run commands is through the Run() method. This should be considered early beta quality at the moment, Jon will be pulling the bits he likes back into his part of the depot after he's reviewed it. |
||
#1 | 4595 | Tony Smith | Copy Jon Parise's PHP integration into my directory. | ||
//guest/jon_parise/api/php/perforce.cpp | |||||
#6 | 4427 | Jon_Parise |
Corrected some compilation issues with older versions of PHP under Windows. Submitted by: ken@demarest.com |
||
#5 | 4349 | Jon_Parise |
Apparently, Visual C++ 6 doesn't like this initializer. Rewrite this line as an assignment. |
||
#4 | 4324 | Jon_Parise |
Adding Win32 support. This includes the addition of a config.w32 Win32 build file, a handful of ZTS fixes, the extraction of the PHPClientUser class (and its p4api header dependency) to a separate header file, and the removal of the p4api_version.h auto-generated file (which may return should I figure out how to generate it using JScript). |
||
#3 | 4293 | Jon_Parise | Use $Header$ keywords instead of $Id$. | ||
#2 | 4292 | Jon_Parise |
Changing these files to the 'ktext' filetype so that the RCS keywords will be expanded. |
||
#1 | 4291 | Jon_Parise | Initial version of the Perforce extension for PHP. |