Index: base/src/pextlib1.0/curl.c
===================================================================
--- base/src/pextlib1.0/curl.c	(revision 124611)
+++ base/src/pextlib1.0/curl.c	(working copy)
@@ -83,6 +83,7 @@
 int SetResultFromCurlMErrorCode(Tcl_Interp* interp, CURLMcode inErrorCode);
 int CurlFetchCmd(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]);
 int CurlIsNewerCmd(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]);
+int CurlModDateCmd(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]);
 int CurlGetSizeCmd(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]);
 int CurlPostCmd(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]);
 
@@ -923,6 +924,214 @@
 }
 
 /**
+ * curl getmoddate subcommand entry point.
+ *
+ * @param interp		current interpreter
+ * @param objc			number of parameters
+ * @param objv			parameters
+ */
+int
+CurlGetModDateCmd(Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[])
+{
+	int theResult = TCL_OK;
+	CURL* theHandle = NULL;
+	FILE* theFile = NULL;
+
+	do {
+		int optioncrsr;
+		int lastoption;
+		int ignoresslcert = 0;
+		long theResponseCode = 0;
+		const char* theURL;
+		CURLcode theCurlCode;
+		long theModDate;
+		char theModDateString[32];
+
+		optioncrsr = 2;
+		lastoption = objc - 2;
+		while (optioncrsr <= lastoption) {
+			/* get the option */
+			const char* theOption = Tcl_GetString(objv[optioncrsr]);
+
+			if (strcmp(theOption, "--ignore-ssl-cert") == 0) {
+				ignoresslcert = 1;
+			} else {
+				Tcl_ResetResult(interp);
+				Tcl_AppendResult(interp, "curl getmoddate: unknown option ", theOption, NULL);
+				theResult = TCL_ERROR;
+				break;
+			}
+
+			optioncrsr++;
+		}
+
+		if (optioncrsr <= lastoption) {
+			/* something went wrong */
+			break;
+		}
+
+		/* first (second) parameter is the url, second (third) parameter is the date */
+		if (objc < 3 || objc > 4) {
+			Tcl_WrongNumArgs(interp, 1, objv, "getmoddate [--ignore-ssl-cert] url date");
+			theResult = TCL_ERROR;
+			break;
+		}
+
+		/* Retrieve the url */
+		theURL = Tcl_GetString(objv[objc - 1]);
+
+		/* Open the file (dev/null) */
+		theFile = fopen("/dev/null", "a");
+		if (theFile == NULL) {
+			Tcl_SetResult(interp, strerror(errno), TCL_VOLATILE);
+			theResult = TCL_ERROR;
+			break;
+		}
+
+		/* Create the CURL handle */
+		if (theHandle == NULL) {
+			/* Re-use existing handle if theHandle isn't NULL */
+			theHandle = curl_easy_init();
+		}
+		/* If we're re-using a handle, the previous call did ensure to reset it
+		 * to the default state using curl_easy_reset(3) */
+
+		/* Setup the handle */
+		theCurlCode = curl_easy_setopt(theHandle, CURLOPT_URL, theURL);
+		if (theCurlCode != CURLE_OK) {
+			theResult = SetResultFromCurlErrorCode(interp, theCurlCode);
+			break;
+		}
+
+		/* -L option */
+		theCurlCode = curl_easy_setopt(theHandle, CURLOPT_FOLLOWLOCATION, 1);
+		if (theCurlCode != CURLE_OK) {
+			theResult = SetResultFromCurlErrorCode(interp, theCurlCode);
+			break;
+		}
+
+		/* --max-redirs option, same default as curl command line */
+		theCurlCode = curl_easy_setopt(theHandle, CURLOPT_MAXREDIRS, 50);
+		if (theCurlCode != CURLE_OK) {
+			theResult = SetResultFromCurlErrorCode(interp, theCurlCode);
+			break;
+		}
+
+		/* echo any cookies received on a redirect */
+		theCurlCode = curl_easy_setopt(theHandle, CURLOPT_COOKIEJAR, "/dev/null");
+		if (theCurlCode != CURLE_OK) {
+			theResult = SetResultFromCurlErrorCode(interp, theCurlCode);
+			break;
+		}
+
+		/* -f option */
+		theCurlCode = curl_easy_setopt(theHandle, CURLOPT_FAILONERROR, 1);
+		if (theCurlCode != CURLE_OK) {
+			theResult = SetResultFromCurlErrorCode(interp, theCurlCode);
+			break;
+		}
+
+		/* set timeout on connections */
+		theCurlCode = curl_easy_setopt(theHandle, CURLOPT_CONNECTTIMEOUT, _CURL_CONNECTION_TIMEOUT);
+		if (theCurlCode != CURLE_OK) {
+			theResult = SetResultFromCurlErrorCode(interp, theCurlCode);
+			break;
+		}
+
+		/* set minimum connection speed */
+		theCurlCode = curl_easy_setopt(theHandle, CURLOPT_LOW_SPEED_LIMIT, _CURL_MINIMUM_XFER_SPEED);
+		if (theCurlCode != CURLE_OK) {
+			theResult = SetResultFromCurlErrorCode(interp, theCurlCode);
+			break;
+		}
+
+		/* set timeout interval for connections < min xfer speed */
+		theCurlCode = curl_easy_setopt(theHandle, CURLOPT_LOW_SPEED_TIME, _CURL_MINIMUM_XFER_TIMEOUT);
+		if (theCurlCode != CURLE_OK) {
+			theResult = SetResultFromCurlErrorCode(interp, theCurlCode);
+			break;
+		}
+
+		/* write to the file */
+		theCurlCode = curl_easy_setopt(theHandle, CURLOPT_WRITEDATA, theFile);
+		if (theCurlCode != CURLE_OK) {
+			theResult = SetResultFromCurlErrorCode(interp, theCurlCode);
+			break;
+		}
+
+		/* we may want to ignore ssl errors */
+		if (ignoresslcert) {
+			theCurlCode = curl_easy_setopt(theHandle, CURLOPT_SSL_VERIFYPEER, (long) 0);
+			if (theCurlCode != CURLE_OK) {
+				theResult = SetResultFromCurlErrorCode(interp, theCurlCode);
+				break;
+			}
+			theCurlCode = curl_easy_setopt(theHandle, CURLOPT_SSL_VERIFYHOST, (long) 0);
+			if (theCurlCode != CURLE_OK) {
+				theResult = SetResultFromCurlErrorCode(interp, theCurlCode);
+				break;
+			}
+		}
+
+		/* save the modification date */
+		theCurlCode = curl_easy_setopt(theHandle, CURLOPT_FILETIME, 1);
+		if (theCurlCode != CURLE_OK) {
+			theResult = SetResultFromCurlErrorCode(interp, theCurlCode);
+			break;
+		}
+
+		/* we do not want any progress */
+		theCurlCode = curl_easy_setopt(theHandle, CURLOPT_NOPROGRESS, 1);
+		if (theCurlCode != CURLE_OK) {
+			theResult = SetResultFromCurlErrorCode(interp, theCurlCode);
+			break;
+		}
+
+		/* actually fetch the resource */
+		theCurlCode = curl_easy_perform(theHandle);
+		if (theCurlCode != CURLE_OK) {
+			theResult = SetResultFromCurlErrorCode(interp, theCurlCode);
+			break;
+		}
+
+		/* close the file */
+		(void) fclose(theFile);
+		theFile = NULL;
+
+		/* check everything went fine */
+		theCurlCode = curl_easy_getinfo(theHandle, CURLINFO_HTTP_CODE, &theResponseCode);
+		if (theCurlCode != CURLE_OK) {
+			theResult = SetResultFromCurlErrorCode(interp, theCurlCode);
+			break;
+		}
+
+		theModDate = 0;
+
+        /* get the modification date */
+        theCurlCode = curl_easy_getinfo(theHandle, CURLINFO_FILETIME, &theModDate);
+        if (theCurlCode != CURLE_OK) {
+            theResult = SetResultFromCurlErrorCode(interp, theCurlCode);
+            break;
+        }
+
+		(void) snprintf(theModDateString, sizeof(theModDateString),
+			"%ld", theModDate);
+		Tcl_SetResult(interp, theModDateString, TCL_VOLATILE);
+	} while (0);
+
+	/* reset the connection */
+	if (theHandle != NULL) {
+		curl_easy_reset(theHandle);
+	}
+
+	if (theFile != NULL) {
+		fclose(theFile);
+	}
+
+	return theResult;
+}
+
+/**
  * curl getsize subcommand entry point.
  *
  * @param interp		current interpreter
@@ -1393,12 +1602,13 @@
 	typedef enum {
 		kCurlFetch,
 		kCurlIsNewer,
+		kCurlGetModDate,
 		kCurlGetSize,
 		kCurlPost
 	} EOption;
 
 	static const char *options[] = {
-		"fetch", "isnewer", "getsize", "post", NULL
+		"fetch", "isnewer", "getmoddate", "getsize", "post", NULL
 	};
 	int theResult = TCL_OK;
 	EOption theOptionIndex;
@@ -1427,6 +1637,9 @@
 		case kCurlIsNewer:
 			theResult = CurlIsNewerCmd(interp, objc, objv);
 			break;
+		case kCurlGetModDate:
+			theResult = CurlGetModDateCmd(interp, objc, objv);
+			break;
 		case kCurlGetSize:
 			theResult = CurlGetSizeCmd(interp, objc, objv);
 			break;
