/* +----------------------------------------------------------------------+ | rpminfo extension for PHP | +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.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@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Remi Collet | +----------------------------------------------------------------------+ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include #include #include #include #include #include "php_rpminfo.h" #ifndef ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE #define ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, type_hint, allow_null, default_value) \ ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) #endif #include "rpminfo_arginfo.h" ZEND_DECLARE_MODULE_GLOBALS(rpminfo) static rpmts rpminfo_getts(void) { if (!RPMINFO_G(ts)) { rpmReadConfigFiles(NULL, NULL); RPMINFO_G(ts) = rpmtsCreate(); } if (RPMINFO_G(ts)) { (void)rpmtsSetVSFlags(RPMINFO_G(ts), _RPMVSF_NODIGESTS | _RPMVSF_NOSIGNATURES | RPMVSF_NOHDRCHK); } return RPMINFO_G(ts); } static rpmdb rpminfo_getdb(void) { if (!RPMINFO_G(db)) { rpmts ts = rpminfo_getts(); rpmtsOpenDB(ts, O_RDONLY); RPMINFO_G(db) = rpmtsGetRdb(ts); } return RPMINFO_G(db); } static void rpm_header_to_zval(zval *return_value, Header h, zend_bool full) { HeaderIterator hi; rpmTagVal tag; rpmTagType type; const char *val; int i; array_init(return_value); hi = headerInitIterator(h); while ((tag=headerNextTag(hi)) != RPMTAG_NOT_FOUND) { if (!full) { switch (tag) { case RPMTAG_NAME: case RPMTAG_VERSION: case RPMTAG_RELEASE: case RPMTAG_EPOCH: case RPMTAG_ARCH: case RPMTAG_SUMMARY: /* Always present tags */ break; default: /* Additional tags */ for (i=0 ; i=0) { key = rpmtdGetUint16(&keys); add_next_index_long(&tmp, (zend_long)*key); } add_assoc_zval(return_value, rpmTagGetName(tag), &tmp); } else { add_assoc_null(return_value, rpmTagGetName(tag)); } } else { add_assoc_long(return_value, rpmTagGetName(tag), (zend_long)headerGetNumber(h, tag)); } break; case RPM_INT32_TYPE: if (rpmTagGetReturnType(tag) == RPM_ARRAY_RETURN_TYPE) { struct rpmtd_s keys; if (headerGet(h, tag, &keys, HEADERGET_MINMEM)) { uint32_t *key; zval tmp; array_init(&tmp); rpmtdInit(&keys); while (rpmtdNext(&keys)>=0) { key = rpmtdGetUint32(&keys); add_next_index_long(&tmp, (zend_long)*key); } add_assoc_zval(return_value, rpmTagGetName(tag), &tmp); } else { add_assoc_null(return_value, rpmTagGetName(tag)); } } else { add_assoc_long(return_value, rpmTagGetName(tag), (zend_long)headerGetNumber(h, tag)); } break; case RPM_INT64_TYPE: if (rpmTagGetReturnType(tag) == RPM_ARRAY_RETURN_TYPE) { struct rpmtd_s keys; if (headerGet(h, tag, &keys, HEADERGET_MINMEM)) { uint64_t *key; zval tmp; array_init(&tmp); rpmtdInit(&keys); while (rpmtdNext(&keys)>=0) { key = rpmtdGetUint64(&keys); add_next_index_long(&tmp, (zend_long)*key); } add_assoc_zval(return_value, rpmTagGetName(tag), &tmp); } else { add_assoc_null(return_value, rpmTagGetName(tag)); } } else { add_assoc_long(return_value, rpmTagGetName(tag), (zend_long)headerGetNumber(h, tag)); } break; case RPM_STRING_ARRAY_TYPE: { struct rpmtd_s keys; if (headerGet(h, tag, &keys, HEADERGET_MINMEM)) { const char *key; zval tmp; array_init(&tmp); while ((key = rpmtdNextString(&keys))) { add_next_index_string(&tmp, key); } add_assoc_zval(return_value, rpmTagGetName(tag), &tmp); } else { add_assoc_null(return_value, rpmTagGetName(tag)); } } break; default: val = headerGetAsString(h, tag); if (val) { add_assoc_string(return_value, rpmTagGetName(tag), headerGetAsString(h, tag)); } else { add_assoc_null(return_value, rpmTagGetName(tag)); } } } headerFreeIterator(hi); if (full) { add_assoc_bool(return_value, "IsSource", headerIsSource(h)); } } /* {{{ proto array rpminfo(string path [, bool full [, string &$error]) Retrieve information from a RPM file */ PHP_FUNCTION(rpminfo) { char *path, *e_msg; size_t len, e_len=0; zend_bool full = 0; zval *error = NULL; FD_t f; Header h; rpmts ts = rpminfo_getts(); if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|bz", &path, &len, &full, &error) == FAILURE) { return; } if (error) { ZVAL_DEREF(error); zval_dtor(error); ZVAL_NULL(error); } f = Fopen(path, "r"); if (f) { int rc; rc = rpmReadPackageFile(ts, f, "rpminfo", &h); if (rc == RPMRC_OK || rc == RPMRC_NOKEY || rc == RPMRC_NOTTRUSTED) { rpm_header_to_zval(return_value, h, full); if (h) { headerFree(h); } Fclose(f); return; } else if (rc == RPMRC_NOTFOUND) { e_len = spprintf(&e_msg, 0, "Can't read '%s': Argument is not a RPM file", path); } else if (rc == RPMRC_NOTFOUND) { e_len = spprintf(&e_msg, 0, "Can't read '%s': Error reading header from package", path); } else { e_len = spprintf(&e_msg, 0, "Can't read '%s': Unkown error", path); } Fclose(f); } else { e_len = spprintf(&e_msg, 0, "Can't open '%s': %s", path, Fstrerror(f)); } if (e_len) { if (error) { ZVAL_STRINGL(error, e_msg, e_len); } else { php_error_docref(NULL, E_WARNING, "%s", e_msg); } efree(e_msg); } RETURN_NULL(); } /* }}} */ /* {{{ proto array rpmdbinfo(string nevr [, bool full]) Retrieve information from an installed RPM */ PHP_FUNCTION(rpmdbinfo) { char *name; size_t len; zend_bool full = 0; Header h; rpmdb db; rpmdbMatchIterator di; if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|b", &name, &len, &full) == FAILURE) { return; } db = rpminfo_getdb(); di = rpmdbInitIterator(db, RPMDBI_LABEL, name, len); if (!di) { // Not found RETURN_NULL(); } array_init(return_value); while ((h = rpmdbNextIterator(di)) != NULL) { zval tmp; rpm_header_to_zval(&tmp, h, full); add_next_index_zval(return_value, &tmp); } rpmdbFreeIterator(di); } /* }}} */ static unsigned char nibble(char c) { if (c >= '0' && c <= '9') { return (c - '0'); } if (c >= 'a' && c <= 'f') { return (c - 'a') + 10; } if (c >= 'A' && c <= 'F') { return (c - 'A') + 10; } return 0; } static int hex2bin(const char *hex, char *bin, int len) { int i; for (i=0 ; (i+1) e2) { RETVAL_LONG(1); } else { // Version p = strchr(v1, '-'); if (p) { r1 = p+1; *p = 0; } else { r1 = empty; } p = strchr(v2, '-'); if (p) { r2 = p+1; *p = 0; } else { r2 = empty; } r = rpmvercmp(v1, v2); if (r) { RETVAL_LONG(r); } else { // Release r = rpmvercmp(r1, r2); RETVAL_LONG(r); } } efree(evr1); efree(evr2); } /* }}} */ /* {{{ proto int rpmaddtag(int tag) add a tag in the default set */ PHP_FUNCTION(rpmaddtag) { int i; zend_long tag; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &tag) == FAILURE) { return; } if (RPMINFO_G(tags)) { for (i=0 ; its = NULL; rpminfo_globals->db = NULL; } /* }}} */ /* {{{ rpminfo_module_entry */ zend_module_entry rpminfo_module_entry = { STANDARD_MODULE_HEADER_EX, NULL, NULL, "rpminfo", ext_functions, PHP_MINIT(rpminfo), NULL, PHP_RINIT(rpminfo), PHP_RSHUTDOWN(rpminfo), PHP_MINFO(rpminfo), PHP_RPMINFO_VERSION, PHP_MODULE_GLOBALS(rpminfo), PHP_GINIT(rpminfo), NULL, NULL, STANDARD_MODULE_PROPERTIES_EX }; /* }}} */ #ifdef COMPILE_DL_RPMINFO #ifdef ZTS ZEND_TSRMLS_CACHE_DEFINE() #endif ZEND_GET_MODULE(rpminfo) #endif /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */