/* * 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/jon_parise/api/php/perforce.cpp#6 $ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.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 "php_perforce.h" #include "php_clientuser.h" /* {{{ Globals */ static zend_class_entry *perforce_class_entry_ptr; static int le_perforce = 0; /* }}} */ /* {{{ php_perforce_object */ struct php_perforce_object { ClientApi *client; PHPClientUser *user; }; /* }}} */ /* 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 = (php_perforce_object *)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; } /* }}} */ /* {{{ call_method(zval *object, char *method, int arg_count, zval **args[]) */ static zval * call_method(zval *object, char *method, int arg_count, zval **args[]) { zval *retval = NULL; zval *function_name; TSRMLS_FETCH(); MAKE_STD_ZVAL(function_name); ZVAL_STRING(function_name, method, 0); if ((call_user_function_ex(EG(function_table), &object, function_name, &retval, arg_count, args, 0, NULL TSRMLS_CC) != SUCCESS) || (!retval)) { const char *class_name = get_class_name(object TSRMLS_CC); php_error(E_WARNING, "PerforceClient is unable to call %s::%s()", (class_name) ? class_name : "Unknown Class", method); ALLOC_INIT_ZVAL(retval); } return retval; } /* }}} */ /* {{{ perforce_error(Error &error) Displays a Perforce error using php_error(). */ static void perforce_error(Error &error) { StrBuf *buffer = new StrBuf; error.Fmt(buffer); php_error(E_NOTICE, "Perforce Error: %s\n", buffer->Text()); delete buffer; } /* }}} */ /* {{{ perforce_destructor(void *object) */ static void perforce_destructor(void *object) { php_perforce_object *perforce = (php_perforce_object *)object; delete perforce->user; delete perforce->client; efree(object); } /* }}} */ /* Perforce Client User */ /* {{{ PHPClientUser::InputData(StrBuf *strbuf, Error *e) */ void PHPClientUser::InputData(StrBuf *strbuf, Error *e) { zval *retval = call_method(object, "InputData", 0, NULL); if (Z_TYPE_P(retval) == IS_STRING) { strbuf->Set(Z_STRVAL_P(retval)); } else { php_error(E_WARNING, "InputData must return a string"); } } /* }}} */ /* {{{ PHPClientUser::HandleError(Error *err) */ void PHPClientUser::HandleError(Error *err) { StrBuf msg; err->Fmt(&msg) ; zval *z_msg; MAKE_STD_ZVAL(z_msg); ZVAL_STRINGL(z_msg, msg.Text(), msg.Length(), 1); zval *z_severity; MAKE_STD_ZVAL(z_severity); ZVAL_LONG(z_severity, err->GetSeverity()); zval ***args = (zval ***) emalloc(sizeof(zval **) * 2); args[0] = &z_msg; args[1] = &z_severity; call_method(object, "HandlerError", 2, args); efree(args); } /* }}} */ /* {{{ PHPClientUser::Message(Error *err) */ void PHPClientUser::Message(Error *err) { StrBuf msg; err->Fmt(&msg) ; zval *z_msg; MAKE_STD_ZVAL(z_msg); ZVAL_STRINGL(z_msg, msg.Text(), msg.Length(), 1); zval *z_severity; MAKE_STD_ZVAL(z_severity); ZVAL_LONG(z_severity, err->GetSeverity()); zval ***args = (zval ***) emalloc(sizeof(zval **) * 2); args[0] = &z_msg; args[1] = &z_severity; call_method(object, "Message", 2, args); efree(args); } /* }}} */ /* {{{ PHPClientUser::OutputError(char *errBuf) */ void PHPClientUser::OutputError(char *errBuf) { zval *z_error; MAKE_STD_ZVAL(z_error); ZVAL_STRING(z_error, errBuf, 1); zval ***args = (zval ***) emalloc(sizeof(zval **) * 1); args[0] = &z_error; call_method(object, "OutputError", 1, args); efree(args); } /* }}} */ /* {{{ PHPClientUser::OutputInfo(char level, char *data) */ void PHPClientUser::OutputInfo(char level, char *data) { zval *z_level; MAKE_STD_ZVAL(z_level); ZVAL_LONG(z_level, level); zval *z_data; MAKE_STD_ZVAL(z_data); ZVAL_STRING(z_data, data, 1); zval ***args = (zval ***) emalloc(sizeof(zval **) * 2); args[0] = &z_level; args[1] = &z_data; call_method(object, "OutputInfo", 2, args); efree(args); } /* }}} */ /* {{{ PHPClientUser::OutputBinary(char *data, int length) */ void PHPClientUser::OutputBinary(char *data, int length) { zval *z_data; MAKE_STD_ZVAL(z_data); ZVAL_STRINGL(z_data, data, length, 1); zval ***args = (zval ***) emalloc(sizeof(zval **) * 1); args[0] = &z_data; call_method(object, "OutputBinary", 1, args); efree(args); } /* }}} */ /* {{{ PHPClientUser::OutputText(char *data, int length) */ void PHPClientUser::OutputText(char *data, int length) { zval *z_data; MAKE_STD_ZVAL(z_data); ZVAL_STRINGL(z_data, data, length, 1); zval ***args = (zval ***) emalloc(sizeof(zval **) * 1); args[0] = &z_data; call_method(object, "OutputText", 1, args); efree(args); } /* }}} */ /* {{{ PHPClientUser::OutputStat(StrDict *varList) */ void PHPClientUser::OutputStat(StrDict *varList) { TSRMLS_FETCH(); zval *z_tags; MAKE_STD_ZVAL(z_tags); if (array_init(z_tags) != SUCCESS) { php_error(E_ERROR, "Failed to initialize array parameter value"); return; } static char * const vars[] = { "tag", "clientFile", "depotFile", "headAction", "headChange", "headRev", "headType", "headTime", "haveRev", "action", "change", "unresolved", "otherOpen", "otherLock", "ourLock", "client", "user", "time", "status", "desc", "dir", "path", "unmap" , 0 }; StrPtr *s; zval *v; MAKE_STD_ZVAL(v); /* Add the known variables to the array. */ for (int i = 0; vars[i]; ++i) { if (s = varList->GetVar(StrRef(vars[i]))) { ZVAL_STRINGL(v, s->Text(), s->Length(), 1); if (zend_hash_update(HASH_OF(z_tags), vars[i], strlen(vars[i]), (void *)&v, sizeof(zval *), NULL) == FAILURE) { php_error(E_ERROR, "Failed to insert ('%s' => '%s') into array", vars[i], s->Text()); } } } zval ***args = (zval ***) emalloc(sizeof(zval **) * 1); args[0] = &z_tags; call_method(object, "OutputStat", 1, args); efree(args); } /* }}} */ /* {{{ PHPClientUser::Prompt(const StrPtr &msg, StrBuf &buf, int bufsiz, Error *e) */ void PHPClientUser::Prompt(const StrPtr &msg, StrBuf &buf, int bufsiz, Error *e) { zval *z_msg; MAKE_STD_ZVAL(z_msg); ZVAL_STRINGL(z_msg, msg.Text(), msg.Length(), 1); zval ***args = (zval ***) emalloc(sizeof(zval **) * 1); args[0] = &z_msg; zval *retval = call_method(object, "Prompt", 1, args); efree(args); if (Z_TYPE_P(retval) == IS_STRING) { buf.Set(Z_STRVAL_P(retval)); } else { php_error(E_WARNING, "Prompt must return a string"); } } /* }}} */ /* {{{ PHPClientUser::ErrorPause(char *errBuf, Error *e) */ void PHPClientUser::ErrorPause(char *errBuf, Error *e) { zval *z_error; MAKE_STD_ZVAL(z_error); ZVAL_STRING(z_error, errBuf, 1); zval ***args = (zval ***) emalloc(sizeof(zval **) * 1); args[0] = &z_error; call_method(object, "ErrorPause", 1, args); efree(args); } /* }}} */ /* {{{ PHPClientUser::Edit(FileSys *f1, Error *e) */ void PHPClientUser::Edit(FileSys *f1, Error *e) { zval *z_filename; MAKE_STD_ZVAL(z_filename); ZVAL_STRING(z_filename, f1->Name(), 1); zval ***args = (zval ***) emalloc(sizeof(zval **) * 1); args[0] = &z_filename; call_method(object, "Edit", 1, args); efree(args); } /* }}} */ /* {{{ PHPClientUser::Diff(FileSys *f1, FileSys *f2, int doPage, char *diffFlags, Error *e) */ void PHPClientUser::Diff(FileSys *f1, FileSys *f2, int doPage, char *diffFlags, Error *e) { zval *z_filename1; MAKE_STD_ZVAL(z_filename1); ZVAL_STRING(z_filename1, f1->Name(), 1); zval *z_filename2; MAKE_STD_ZVAL(z_filename2); ZVAL_STRING(z_filename2, f2->Name(), 1); zval *z_do_page; MAKE_STD_ZVAL(z_do_page); ZVAL_LONG(z_do_page, doPage); zval *z_diff_flags; MAKE_STD_ZVAL(z_diff_flags); ZVAL_STRING(z_diff_flags, diffFlags, 1); zval ***args = (zval ***) emalloc(sizeof(zval **) * 4); args[0] = &z_filename1; args[1] = &z_filename2; args[2] = &z_do_page; args[3] = &z_diff_flags; call_method(object, "Diff", 4, args); efree(args); } /* }}} */ /* {{{ PHPClientUser::Merge(FileSys *base, FileSys *leg1, FileSys *leg2, FileSys *result, Error *e) */ void PHPClientUser::Merge(FileSys *base, FileSys *leg1, FileSys *leg2, FileSys *result, Error *e) { zval *z_base_filename; MAKE_STD_ZVAL(z_base_filename); ZVAL_STRING(z_base_filename, base->Name(), 1); zval *z_leg1_filename; MAKE_STD_ZVAL(z_leg1_filename); ZVAL_STRING(z_leg1_filename, leg1->Name(), 1); zval *z_leg2_filename; MAKE_STD_ZVAL(z_leg2_filename); ZVAL_STRING(z_leg2_filename, leg2->Name(), 1); zval *z_result_filename; MAKE_STD_ZVAL(z_result_filename); ZVAL_STRING(z_result_filename, result->Name(), 1); zval ***args = (zval ***) emalloc(sizeof(zval **) * 4); args[0] = &z_base_filename; args[1] = &z_leg1_filename; args[2] = &z_leg2_filename; args[3] = &z_result_filename; call_method(object, "Merge", 4, args); efree(args); } /* }}} */ /* {{{ PHPClientUser::Help(char * const *help) */ void PHPClientUser::Help(char * const *help) { TSRMLS_FETCH(); zval *z_help; MAKE_STD_ZVAL(z_help); if (array_init(z_help) != SUCCESS) { php_error(E_ERROR, "Failed to initialize array parameter value"); return; } zval *line; MAKE_STD_ZVAL(line); while (*help) { /* Read a full line of help text (until the NUL). */ ZVAL_STRING(line, (char *)help, 1); /* Insert this line of help text into the next slot of the array. */ if (zend_hash_next_index_insert(HASH_OF(z_help), (void *)&line, sizeof(zval *), NULL) == FAILURE) { php_error(E_ERROR, "Failed to insert new line into array"); } /* Jump over the NUL character. There may be more text waiting. */ help += 1; } zval ***args = (zval ***) emalloc(sizeof(zval **) * 1); args[0] = &z_help; call_method(object, "Help", 1, args); efree(args); } /* }}} */ /* PerforceClient Methods */ /* {{{ proto void constructor(object ui) */ #ifdef ZEND_ENGINE_2 PHP_METHOD(PerforceClient, __construct) #else PHP_METHOD(PerforceClient, perforceclient) #endif { php_perforce_object *perforce = NULL; zval *ui; int ret; /* We expect a single parameter: the ClientUser UI object. */ if (zend_parse_parameters(1 TSRMLS_CC, "o", &ui) == FAILURE) { return; } /* Initialize our new PerforceClient object. */ object_init_ex(this_ptr, perforce_class_entry_ptr); /* Create the Perforce Client objects. */ perforce = (php_perforce_object *)emalloc(sizeof(php_perforce_object)); perforce->user = new PHPClientUser(); perforce->client = new ClientApi(perforce->user); /* Assign the ClientUser UI object to our management structure. */ perforce->user->object = ui; zval_copy_ctor(perforce->user->object); /* 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 setPort(string port) */ PHP_METHOD(PerforceClient, setPort) { php_perforce_object *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->client->SetPort(port); RETURN_TRUE; } /* }}} */ /* {{{ proto string getPort() */ PHP_METHOD(PerforceClient, getPort) { php_perforce_object *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr port(perforce->client->GetPort()); RETURN_STRINGL(port.Text(), port.Length(), 1); } /* }}} */ /* {{{ proto bool setUser(string user) */ PHP_METHOD(PerforceClient, setUser) { php_perforce_object *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->client->SetUser(user); RETURN_TRUE; } /* }}} */ /* {{{ proto string getUser() */ PHP_METHOD(PerforceClient, getUser) { php_perforce_object *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr user(perforce->client->GetUser()); RETURN_STRINGL(user.Text(), user.Length(), 1); } /* }}} */ /* {{{ proto bool setPassword(string password) */ PHP_METHOD(PerforceClient, setPassword) { php_perforce_object *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->client->SetPassword(password); RETURN_TRUE; } /* }}} */ /* {{{ proto string getPassword() */ PHP_METHOD(PerforceClient, getPassword) { php_perforce_object *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr password(perforce->client->GetPassword()); RETURN_STRINGL(password.Text(), password.Length(), 1); } /* }}} */ /* {{{ proto bool setClient(string client) */ PHP_METHOD(PerforceClient, setClient) { php_perforce_object *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->client->SetClient(client); RETURN_TRUE; } /* }}} */ /* {{{ proto string getClient() */ PHP_METHOD(PerforceClient, getClient) { php_perforce_object *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr client(perforce->client->GetClient()); RETURN_STRINGL(client.Text(), client.Length(), 1); } /* }}} */ /* {{{ proto bool setProtocol(string protocol) */ PHP_METHOD(PerforceClient, setProtocol) { php_perforce_object *perforce; char *protocol, *value; int protocol_len, value_len; if (zend_parse_parameters(2 TSRMLS_CC, "ss", &protocol, &protocol_len, &value, &value_len) == FAILURE) { return; } PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; perforce->client->SetProtocol(protocol, value); RETURN_TRUE; } /* }}} */ /* {{{ proto string getProtocol(string protocol) */ PHP_METHOD(PerforceClient, getProtocol) { php_perforce_object *perforce; char *protocol; int len; if (zend_parse_parameters(1 TSRMLS_CC, "s", &protocol, &len) == FAILURE) { return; } PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr *value = perforce->client->GetProtocol(protocol); RETURN_STRINGL(value->Text(), value->Length(), 1); } /* }}} */ /* {{{ proto bool setCwd(string cwd) */ PHP_METHOD(PerforceClient, setCwd) { php_perforce_object *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->client->SetCwd(cwd); RETURN_TRUE; } /* }}} */ /* {{{ proto string getCwd() */ PHP_METHOD(PerforceClient, getCwd) { php_perforce_object *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr cwd(perforce->client->GetCwd()); RETURN_STRINGL(cwd.Text(), cwd.Length(), 1); } /* }}} */ /* {{{ proto bool setCharset(string charset) */ PHP_METHOD(PerforceClient, setCharset) { php_perforce_object *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->client->SetCharset(charset); RETURN_TRUE; } /* }}} */ /* {{{ proto string getCharset() */ PHP_METHOD(PerforceClient, getCharset) { php_perforce_object *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr charset(perforce->client->GetCharset()); RETURN_STRINGL(charset.Text(), charset.Length(), 1); } /* }}} */ /* {{{ proto bool setHost(string host) */ PHP_METHOD(PerforceClient, setHost) { php_perforce_object *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->client->SetHost(host); RETURN_TRUE; } /* }}} */ /* {{{ proto string getHost() */ PHP_METHOD(PerforceClient, getHost) { php_perforce_object *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr host(perforce->client->GetHost()); RETURN_STRINGL(host.Text(), host.Length(), 1); } /* }}} */ /* {{{ proto bool setLanguage(string language) */ PHP_METHOD(PerforceClient, setLanguage) { php_perforce_object *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->client->SetLanguage(language); RETURN_TRUE; } /* }}} */ /* {{{ proto string getLanguage() */ PHP_METHOD(PerforceClient, getLanguage) { php_perforce_object *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr language(perforce->client->GetLanguage()); RETURN_STRINGL(language.Text(), language.Length(), 1); } /* }}} */ /* {{{ proto string getOs() */ PHP_METHOD(PerforceClient, getOs) { php_perforce_object *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; const StrPtr os(perforce->client->GetOs()); RETURN_STRINGL(os.Text(), os.Length(), 1); } /* }}} */ /* {{{ proto bool init() Establish the connection. */ PHP_METHOD(PerforceClient, init) { Error error; php_perforce_object *perforce = NULL; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; if (perforce == NULL) { php_error(E_ERROR, "Failed to retrieve Perforce connection resource"); RETURN_FALSE; } perforce->client->Init(&error); if (error.Test()) { perforce_error(error); RETURN_FALSE; } RETURN_TRUE; } /* }}} */ /* {{{ proto int final() Close the connection and return the error count. */ PHP_METHOD(PerforceClient, final) { php_perforce_object *perforce; int error_count = 0; Error error; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; error_count = perforce->client->Final(&error); if (error.Test()) { perforce_error(error); } RETURN_LONG(error_count); } /* }}} */ /* {{{ proto bool dropped() Check if the connection is still open. */ PHP_METHOD(PerforceClient, dropped) { php_perforce_object *perforce; PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; if (perforce == NULL) { php_error(E_ERROR, "Failed to retrieve Perforce connection resource"); RETURN_FALSE; } RETURN_BOOL(perforce->client->Dropped() != 0); } /* }}} */ /* {{{ proto bool setArgs() Set the arguments for the next Perforce command. */ PHP_METHOD(PerforceClient, setArgs) { php_perforce_object *perforce; zval *args; zval **item; int i = 0; if (zend_parse_parameters(1 TSRMLS_CC, "a", &args) == FAILURE) { return; } int argc = zend_hash_num_elements(Z_ARRVAL_P(args)); char **argv = (char **) emalloc(sizeof(char *) * argc); zend_hash_internal_pointer_reset(Z_ARRVAL_P(args)); /* Iterate over the array elements */ while (zend_hash_get_current_data(Z_ARRVAL_P(args), (void **)&item) == SUCCESS) { if (i > argc) { php_error(E_ERROR, "Encountered too many items in array"); break; } /* Add the string value of this item to the args and advance. */ convert_to_string_ex(item); argv[i++] = Z_STRVAL_PP(item); zend_hash_move_forward(Z_ARRVAL_P(args)); } PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; perforce->client->SetArgv(argc, argv); efree(argv); RETURN_TRUE; } /* }}} */ /* {{{ proto bool run(string command) Run a Perforce command. */ PHP_METHOD(PerforceClient, run) { php_perforce_object *perforce; char *command; int len; if (zend_parse_parameters(1 TSRMLS_CC, "s", &command, &len) == FAILURE) { return; } PHP_PERFORCE_FETCH(perforce); if (!perforce) RETURN_FALSE; perforce->client->Run(command); RETURN_TRUE; } /* }}} */ /* {{{ 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, 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, setProtocol, NULL, 0) PHP_ME(PerforceClient, getProtocol, 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, init, NULL, 0) PHP_ME(PerforceClient, final, NULL, 0) PHP_ME(PerforceClient, dropped, NULL, 0) PHP_ME(PerforceClient, setArgs, NULL, 0) PHP_ME(PerforceClient, run, NULL, 0) #ifndef ZEND_ENGINE_2 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, setprotocol, setProtocol, NULL, 0) PHP_MALIAS(PerforceClient, getprotocol, getProtocol, 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, setargs, setArgs, 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 | |
---|---|---|---|---|---|
#22 | 7624 | Jon Parise | Avoiding a warning about string literal to char* conversion. | ||
#21 | 7623 | Jon Parise |
The ZEND_BEGIN_ARG_INFO_EX macro now specifies the 'static' keyword itself, so don't want to specific it ourself. |
||
#20 | 6169 | Jon_Parise |
The internal object code has been rewritten to take advantage of the PHP5-specific object model. |
||
#19 | 6168 | Jon_Parise | Bumping copyright years. | ||
#18 | 6148 | Jon_Parise | Tagging the module with the 1.0 version number. | ||
#17 | 6129 | Jon_Parise |
Removing the runTag() and waitTag() methods because support for them has been deprecated in the official P4API. Also, the C++ object memory allocation approach has been simplified. |
||
#16 | 6094 | Jon_Parise | setArgs() now accepts either an array of arguments or individual arguments. | ||
#15 | 6092 | Jon_Parise |
Fixing support for tagged output. We also now return all of the tags (unfiltered) to the user's OutputStat() implementation. |
||
#14 | 6087 | Jon_Parise | Wrapping the rest of the client API and adding argument info to the native PerforceClient methods. | ||
#13 | 6082 | Jon_Parise | Allocate memory for our C++ objects using PHP's memory manager. | ||
#12 | 6081 | Jon_Parise |
Simplifying the method calling code a little bit so that it only searches within the known clientuser class entry's function table. We can also get rid of the get_class_name() helper function. |
||
#11 | 6080 | Jon_Parise | Rewriting the method calling routines to avoid heap allocation for arguments. | ||
#10 | 6079 | Jon_Parise |
We now use a formal interface to define the UI object. This requires PHP5 so all PHP4 support has been removed. A number of other small code improvements are also included. |
||
#9 | 6078 | Jon_Parise | Updating copyright years. | ||
#8 | 6065 | Jon_Parise | Removing PHP 4 (pre- Zend Engine 2) compatibility. | ||
#7 | 6055 | Jon_Parise | Updating to work with the Perforce 2007.2 API. | ||
#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. |