From: Gustavo André dos Santos Lopes <cataphract@php.net>
Date: Mon, 11 Oct 2010 02:48:23 +0000 (+0000)
Subject: - [DOC] Added a 5th parameter to dns_get_record, a boolean that tells whether to... 
X-Git-Tag: php-5.4.0alpha1~191^2~801
X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=91f64706c2579764e23664812897ca2a466d7218;p=php

- [DOC] Added a 5th parameter to dns_get_record, a boolean that tells whether to activate
  "raw mode". In this mide, $type (2nd parameter) is the numeric type of the record, and
  the responses are not parsed -- the "type" element will be numeric and there will be
  a "data" element with the raw data of the response buffer, which the programmer will
  have to parse.
- Fixed bug in the Win32 implementation of dns_get_record, where the 3rd and 4th arguments
  would only be filled if the 2nd ($type) was DNS_ANY.
- [DOC] The 3rd and 4th parameters can now be NULL (changed their arginfo).
---

diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index a70a5b222b..6991972119 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -996,11 +996,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_dns_check_record, 0, 0, 1)
 ZEND_END_ARG_INFO()
 
 # if defined(PHP_WIN32) || HAVE_FULL_DNS_FUNCS
-ZEND_BEGIN_ARG_INFO_EX(arginfo_dns_get_record, 1, 0, 1)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_dns_get_record, 0, 0, 1)
 	ZEND_ARG_INFO(0, hostname)
 	ZEND_ARG_INFO(0, type)
-	ZEND_ARG_INFO(1, authns) /* ARRAY_INFO(1, authns, 1) */
-	ZEND_ARG_INFO(1, addtl)  /* ARRAY_INFO(1, addtl, 1) */
+	ZEND_ARG_ARRAY_INFO(1, authns, 1)
+	ZEND_ARG_ARRAY_INFO(1, addtl, 1)
+	ZEND_ARG_INFO(0, raw)
 ZEND_END_ARG_INFO()
 
 ZEND_BEGIN_ARG_INFO_EX(arginfo_dns_get_mx, 0, 0, 2)
diff --git a/ext/standard/dns.c b/ext/standard/dns.c
index 22c44525e4..dfbe7defd0 100644
--- a/ext/standard/dns.c
+++ b/ext/standard/dns.c
@@ -403,7 +403,7 @@ PHP_FUNCTION(dns_check_record)
 #if HAVE_FULL_DNS_FUNCS
 
 /* {{{ php_parserr */
-static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int store, zval **subarray)
+static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int store, int raw, zval **subarray)
 {
 	u_short type, class, dlen;
 	u_long ttl;
@@ -439,6 +439,16 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int
 	array_init(*subarray);
 
 	add_assoc_string(*subarray, "host", name, 1);
+	add_assoc_string(*subarray, "class", "IN", 1);
+	add_assoc_long(*subarray, "ttl", ttl);
+
+	if (raw) {
+		add_assoc_long(*subarray, "type", type);
+		add_assoc_stringl(*subarray, "data", (char*) cp, (uint) dlen, 1);
+		cp += dlen;
+		return cp;
+	}
+
 	switch (type) {
 		case DNS_T_A:
 			add_assoc_string(*subarray, "type", "A", 1);
@@ -679,20 +689,12 @@ static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int
 			add_assoc_string(*subarray, "replacement", name, 1);
 			break;
 		default:
-			{
-				char buf[10]; /* max length of short + sizeof(id #) */
-				snprintf(buf, 10, "id #%hu", type);
-				buf[10-1] = '\0';
-				add_assoc_string(*subarray, "type", buf, 1);
-				add_assoc_stringl(*subarray, "data", (char*) cp, (uint) dlen, 1);
-				cp += dlen;
-				break;
-			}
+			zval_ptr_dtor(subarray);
+			*subarray = NULL;
+			cp += dlen;
+			break;
 	}
 
-	add_assoc_string(*subarray, "class", "IN", 1);
-	add_assoc_long(*subarray, "ttl", ttl);
-
 	return cp;
 }
 /* }}} */
@@ -720,8 +722,10 @@ PHP_FUNCTION(dns_get_record)
 	u_char *cp = NULL, *end = NULL;
 	int n, qd, an, ns = 0, ar = 0;
 	int type, first_query = 1, store_results = 1;
+	zend_bool raw = 0;
 
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lzz", &hostname, &hostname_len, &type_param, &authns, &addtl) == FAILURE) {
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz!z!b",
+			&hostname, &hostname_len, &type_param, &authns, &addtl, &raw) == FAILURE) {
 		return;
 	}
 
@@ -735,9 +739,17 @@ PHP_FUNCTION(dns_get_record)
 		addtl_recs = 1;
 	}
 
-	if (type_param & ~PHP_DNS_ALL && type_param != PHP_DNS_ANY) {
-		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type '%ld' not supported", type_param);
-		RETURN_FALSE;
+	if (!raw) {
+		if ((type_param & ~PHP_DNS_ALL) && (type_param != PHP_DNS_ANY)) {
+			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type '%ld' not supported", type_param);
+			RETURN_FALSE;
+		}
+	} else {
+		if ((type_param < 1) || (type_param > 0xFFFF)) {
+			php_error_docref(NULL TSRMLS_CC, E_WARNING,
+				"Numeric DNS record type must be between 1 and 65535, '%ld' given", type_param);
+			RETURN_FALSE;
+		}
 	}
 
 	/* Initialize the return array */
@@ -748,13 +760,29 @@ PHP_FUNCTION(dns_get_record)
 	 *   store_results is used to skip storing the results retrieved in step
 	 *   NUMTYPES+1 when results were already fetched.
 	 * - In case of PHP_DNS_ANY we use the directly fetch DNS_T_ANY. (step NUMTYPES+1 )
+	 * - In case of raw mode, we query only the requestd type instead of looping type by type
+	 *   before going with the additional info stuff.
 	 */
-	for (type = (type_param == PHP_DNS_ANY ? (PHP_DNS_NUM_TYPES + 1) : 0);
+
+	if (raw) {
+		type = -1;
+	} else if (type_param == PHP_DNS_ANY) {
+		type = PHP_DNS_NUM_TYPES + 1;
+	} else {
+		type = 0;
+	}
+
+	for ( ;
 		type < (addtl_recs ? (PHP_DNS_NUM_TYPES + 2) : PHP_DNS_NUM_TYPES) || first_query;
 		type++
 	) {
 		first_query = 0;
 		switch (type) {
+			case -1: /* raw */
+				type_to_fetch = type_param;
+				/* skip over the rest and go directly to additional records */
+				type = PHP_DNS_NUM_TYPES - 1;
+				break;
 			case 0:
 				type_to_fetch = type_param&PHP_DNS_A     ? DNS_T_A     : 0;
 				break;
@@ -846,7 +874,7 @@ PHP_FUNCTION(dns_get_record)
 			while (an-- && cp && cp < end) {
 				zval *retval;
 
-				cp = php_parserr(cp, &answer, type_to_fetch, store_results, &retval);
+				cp = php_parserr(cp, &answer, type_to_fetch, store_results, raw, &retval);
 				if (retval != NULL && store_results) {
 					add_next_index_zval(return_value, retval);
 				}
@@ -859,7 +887,7 @@ PHP_FUNCTION(dns_get_record)
 				while (ns-- > 0 && cp && cp < end) {
 					zval *retval = NULL;
 
-					cp = php_parserr(cp, &answer, DNS_T_ANY, authns != NULL, &retval);
+					cp = php_parserr(cp, &answer, DNS_T_ANY, authns != NULL, raw, &retval);
 					if (retval != NULL) {
 						add_next_index_zval(authns, retval);
 					}
@@ -871,7 +899,7 @@ PHP_FUNCTION(dns_get_record)
 				while (ar-- > 0 && cp && cp < end) {
 					zval *retval = NULL;
 
-					cp = php_parserr(cp, &answer, DNS_T_ANY, 1, &retval);
+					cp = php_parserr(cp, &answer, DNS_T_ANY, 1, raw, &retval);
 					if (retval != NULL) {
 						add_next_index_zval(addtl, retval);
 					}
diff --git a/ext/standard/dns_win32.c b/ext/standard/dns_win32.c
index a86cc06a1e..ba1c5a1abf 100644
--- a/ext/standard/dns_win32.c
+++ b/ext/standard/dns_win32.c
@@ -133,7 +133,7 @@ PHP_FUNCTION(dns_check_record)
 /* }}} */
 
 /* {{{ php_parserr */
-static void php_parserr(PDNS_RECORD pRec, int type_to_fetch, int store, zval **subarray)
+static void php_parserr(PDNS_RECORD pRec, int type_to_fetch, int store, int raw, zval **subarray)
 {
 	int type;
 	u_long ttl;
@@ -153,6 +153,15 @@ static void php_parserr(PDNS_RECORD pRec, int type_to_fetch, int store, zval **s
 	array_init(*subarray);
 
 	add_assoc_string(*subarray, "host", pRec->pName, 1);
+	add_assoc_string(*subarray, "class", "IN", 1);
+	add_assoc_long(*subarray, "ttl", ttl);
+
+	if (raw) {
+		add_assoc_long(*subarray, "type", type);
+		add_assoc_stringl(*subarray, "data", (char*) &pRec->Data, (uint) pRec->wDataLength, 1);
+		return;
+	}
+
 	switch (type) {
 		case DNS_TYPE_A: {
 			IN_ADDR ipaddr;
@@ -303,9 +312,9 @@ static void php_parserr(PDNS_RECORD pRec, int type_to_fetch, int store, zval **s
 			}
 			break;
 
+#if _MSC_VER >= 1500
 		case DNS_TYPE_NAPTR:
 			{
-#if _MSC_VER >= 1500
 				DNS_NAPTR_DATA * data_naptr = &pRec->Data.Naptr;
 
 				add_assoc_string(*subarray, "type", "NAPTR", 1);
@@ -315,23 +324,17 @@ static void php_parserr(PDNS_RECORD pRec, int type_to_fetch, int store, zval **s
 				add_assoc_string(*subarray, "services", data_naptr->pService, 1);
 				add_assoc_string(*subarray, "regex", data_naptr->pRegularExpression, 1);
 				add_assoc_string(*subarray, "replacement", data_naptr->pReplacement, 1);
-#endif
 			}
 			break;
+#endif
 
 		default:
-			{
-				char buf[10]; /* max length of short + sizeof(id #) */
-				snprintf(buf, 10, "id #%hu", (unsigned short) type);
-				buf[10-1] = '\0';
-				add_assoc_string(*subarray, "type", buf, 1);
-				add_assoc_stringl(*subarray, "data", (char*) &pRec->Data, (uint) pRec->wDataLength, 1);
-				break;
-			}
+			/* unkown type */
+			zval_ptr_dtor(subarray);
+			*subarray = NULL;
+			return;
 	}
 
-	add_assoc_string(*subarray, "class", "IN", 1);
-	add_assoc_long(*subarray, "ttl", ttl);
 }
 /* }}} */
 
@@ -345,8 +348,10 @@ PHP_FUNCTION(dns_get_record)
 	zval *authns = NULL, *addtl = NULL;
 	int type, type_to_fetch, first_query = 1, store_results = 1;
 	int addtl_recs = 0;
+	zend_bool raw = 0;
 
-	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lzz", &hostname, &hostname_len, &type_param, &authns, &addtl) == FAILURE) {
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz!z!b",
+			&hostname, &hostname_len, &type_param, &authns, &addtl, &raw) == FAILURE) {
 		return;
 	}
 
@@ -357,17 +362,34 @@ PHP_FUNCTION(dns_get_record)
 	if (addtl) {
 		zval_dtor(addtl);
 		array_init(addtl);
+		addtl_recs = 1;
 	}
 
-	if (type_param & ~PHP_DNS_ALL && type_param != PHP_DNS_ANY) {
-		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type '%ld' not supported", type_param);
-		RETURN_FALSE;
+	if (!raw) {
+		if ((type_param & ~PHP_DNS_ALL) && (type_param != PHP_DNS_ANY)) {
+			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type '%ld' not supported", type_param);
+			RETURN_FALSE;
+		}
+	} else {
+		if ((type_param < 1) || (type_param > 0xFFFF)) {
+			php_error_docref(NULL TSRMLS_CC, E_WARNING,
+				"Numeric DNS record type must be between 1 and 65535, '%ld' given", type_param);
+			RETURN_FALSE;
+		}
 	}
 
 	/* Initialize the return array */
 	array_init(return_value);
 
-	for (type = (type_param == PHP_DNS_ANY ? (PHP_DNS_NUM_TYPES + 1) : 0);
+	if (raw) {
+		type = -1;
+	} else if (type_param == PHP_DNS_ANY) {
+		type = PHP_DNS_NUM_TYPES + 1;
+	} else {
+		type = 0;
+	}
+
+	for ( ;
 		type < (addtl_recs ? (PHP_DNS_NUM_TYPES + 2) : PHP_DNS_NUM_TYPES) || first_query;
 		type++
 	) {
@@ -376,6 +398,11 @@ PHP_FUNCTION(dns_get_record)
 
 		first_query = 0;
 		switch (type) {
+			case -1: /* raw */
+				type_to_fetch = type_param;
+				/* skip over the rest and go directly to additional records */
+				type = PHP_DNS_NUM_TYPES - 1;
+				break;
 			case 0:
 				type_to_fetch = type_param&PHP_DNS_A     ? DNS_TYPE_A     : 0;
 				break;
@@ -439,7 +466,7 @@ PHP_FUNCTION(dns_get_record)
 				zval *retval = NULL;
 
 				if (pRec->Flags.S.Section == DnsSectionAnswer) {
-					php_parserr(pRec, type_to_fetch, store_results, &retval);
+					php_parserr(pRec, type_to_fetch, store_results, raw, &retval);
 					if (retval != NULL && store_results) {
 						add_next_index_zval(return_value, retval);
 					}
@@ -447,7 +474,7 @@ PHP_FUNCTION(dns_get_record)
 
 				if (authns && pRec->Flags.S.Section == DnsSectionAuthority) {
 
-					php_parserr(pRec, type_to_fetch, store_results, &retval);
+					php_parserr(pRec, type_to_fetch, 1, raw, &retval);
 					if (retval != NULL) {
 						add_next_index_zval(authns, retval);
 					}
@@ -462,7 +489,7 @@ PHP_FUNCTION(dns_get_record)
 # endif
 #endif
 				if (addtl && pRec->Flags.S.Section == DnsSectionAdditional) {
-					php_parserr(pRec, type_to_fetch, store_results, &retval);
+					php_parserr(pRec, type_to_fetch, 1, raw, &retval);
 					if (retval != NULL) {
 						add_next_index_zval(addtl, retval);
 					}